You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用bigint比较两组long long乘积的大小?

多long long乘积比较的无精度误差优化方案

问题背景

需要判断四个long long乘积的大小关系,但存在以下限制:

  • 禁止使用bigint或__int128
  • 转换为long double会因精度丢失导致错误结果
    已知四个long long的乘积为256位,但99.99%的场景下差异出现在最后128位(多数集中在最后64位),需要在保证完全精确的前提下,优化平均运行速度。此前的高位低位拆分思路被指出本质等同于实现bigint,效率不足。

优化思路

  • 优先快速判断低阶差异:利用绝大多数差异出现在最后64位的特性,先计算两个乘积的低64位(借助unsigned long long的溢出特性自然取模2^64),若低64位能区分大小,直接返回结果,这一步覆盖99.99%的场景。
  • 低阶相等时再处理高阶:仅当低64位完全相等时,再计算乘积的高阶部分(即去掉低64位后的剩余值),通过拆分乘法的方式计算256位乘积的高阶部分,避免完整计算大整数。

代码实现

#include <cstdint>
#include <cstdlib>

bool is_product_greater(long long a, long long b, long long c, long long d,
                        long long e, long long f, long long g, long long h) {
    // 计算左右乘积的符号位
    int sign_left = ((a < 0) ^ (b < 0) ^ (c < 0) ^ (d < 0)) ? -1 : 1;
    int sign_right = ((e < 0) ^ (f < 0) ^ (g < 0) ^ (h < 0)) ? -1 : 1;
    
    // 符号不同直接判断
    if (sign_left != sign_right) {
        return sign_left > sign_right;
    }
    
    // 转为无符号整数处理绝对值乘积比较
    uint64_t ua = llabs(static_cast<int64_t>(a));
    uint64_t ub = llabs(static_cast<int64_t>(b));
    uint64_t uc = llabs(static_cast<int64_t>(c));
    uint64_t ud = llabs(static_cast<int64_t>(d));
    uint64_t ue = llabs(static_cast<int64_t>(e));
    uint64_t uf = llabs(static_cast<int64_t>(f));
    uint64_t ug = llabs(static_cast<int64_t>(g));
    uint64_t uh = llabs(static_cast<int64_t>(h));
    
    // 第一步:计算低64位乘积,利用unsigned溢出自然取模2^64
    auto mul_low64 = [](uint64_t x, uint64_t y) -> uint64_t {
        return x * y;
    };
    
    uint64_t low_left = mul_low64(mul_low64(ua, ub), mul_low64(uc, ud));
    uint64_t low_right = mul_low64(mul_low64(ue, uf), mul_low64(ug, uh));
    
    // 根据符号判断低64位的比较结果
    if (sign_left == 1) {
        if (low_left != low_right) {
            return low_left > low_right;
        }
    } else {
        // 负数乘积,低64位越大,整体值越小
        if (low_left != low_right) {
            return low_left < low_right;
        }
    }
    
    // 第二步:低64位相等,计算乘积的高阶部分
    // 计算两个64位整数相乘的高64位
    auto mul_high64 = [](uint64_t x, uint64_t y) -> uint64_t {
        uint32_t xh = static_cast<uint32_t>(x >> 32);
        uint32_t xl = static_cast<uint32_t>(x);
        uint32_t yh = static_cast<uint32_t>(y >> 32);
        uint32_t yl = static_cast<uint32_t>(y);
        
        uint64_t xl_yl = static_cast<uint64_t>(xl) * yl;
        uint64_t xl_yh = static_cast<uint64_t>(xl) * yh;
        uint64_t xh_yl = static_cast<uint64_t>(xh) * yl;
        uint64_t xh_yh = static_cast<uint64_t>(xh) * yh;
        
        uint64_t carry = (xl_yl >> 32) + (xl_yh & 0xFFFFFFFFULL) + (xh_yl & 0xFFFFFFFFULL);
        return xh_yh + (xl_yh >> 32) + (xh_yl >> 32) + (carry >> 32);
    };
    
    // 计算左边ab*cd的高阶部分
    uint64_t ab_low = ua * ub;
    uint64_t ab_high = mul_high64(ua, ub);
    uint64_t cd_low = uc * ud;
    uint64_t cd_high = mul_high64(uc, ud);
    
    uint64_t mid_term_low = mul_low64(ab_high, cd_low) + mul_low64(ab_low, cd_high);
    uint64_t mid_term_high = mul_high64(ab_high, cd_low) + mul_high64(ab_low, cd_high);
    // 处理mid_term_low的进位
    if (mid_term_low < mul_low64(ab_high, cd_low)) {
        mid_term_high++;
    }
    
    uint64_t left_high = mul_low64(ab_high, cd_high) + mid_term_high;
    
    // 计算右边ef*gh的高阶部分
    uint64_t ef_low = ue * uf;
    uint64_t ef_high = mul_high64(ue, uf);
    uint64_t gh_low = ug * uh;
    uint64_t gh_high = mul_high64(ug, uh);
    
    uint64_t right_mid_low = mul_low64(ef_high, gh_low) + mul_low64(ef_low, gh_high);
    uint64_t right_mid_high = mul_high64(ef_high, gh_low) + mul_high64(ef_low, gh_high);
    if (right_mid_low < mul_low64(ef_high, gh_low)) {
        right_mid_high++;
    }
    
    uint64_t right_high = mul_low64(ef_high, gh_high) + right_mid_high;
    
    // 根据符号返回高阶比较结果
    if (sign_left == 1) {
        return left_high > right_high;
    } else {
        return left_high < right_high;
    }
}

方案优势

  • 平均速度极快:99.99%的场景只需计算低64位即可得出结果,无需进入复杂的高阶计算。
  • 完全精确:所有计算基于整数运算,无浮点转换的精度损失,也未使用bigint或__int128。
  • 符号处理完善:先通过异或判断乘积符号,符号不同直接返回,避免无符号计算的干扰。

内容的提问来源于stack exchange,提问作者sibillalazzerini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 03:25:20