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

如何可移植实现64位宽转128位乘法的高64位计算?

实现64位整数宽乘法取高64位(无符号/有符号)

要求用仅依赖stdint.h的可移植C代码,模拟x86-64的mul和imul指令行为,计算两个64位整数的128位乘积后返回高64位,且无未定义行为。

无符号版本:uint64_t mul128hi(uint64_t lhs, uint64_t rhs)

实现思路

将64位整数拆分为高32位和低32位,利用乘法展开式计算:
设 lhs = a << 32 | b,rhs = c << 32 | d(a、b、c、d均为32位无符号数),则:

lhs * rhs = (a*c) << 64 | ((a*d + b*c) << 32) | (b*d)

高64位由三部分组成:a*c、(a*d + b*c + (b*d的高32位))右移32位的结果,需处理中间进位避免溢出。

代码实现

#include <stdint.h>

uint64_t mul128hi(uint64_t lhs, uint64_t rhs) {
    // 拆分64位为高/低32位
    const uint32_t a = (uint32_t)(lhs >> 32);
    const uint32_t b = (uint32_t)lhs;
    const uint32_t c = (uint32_t)(rhs >> 32);
    const uint32_t d = (uint32_t)rhs;

    // 计算四个32x32乘积(结果为64位,无溢出)
    const uint64_t ac = (uint64_t)a * c;
    const uint64_t ad = (uint64_t)a * d;
    const uint64_t bc = (uint64_t)b * c;
    const uint64_t bd = (uint64_t)b * d;

    // 计算中间项:ad + bc + bd的高32位
    const uint64_t mid = ad + bc + (bd >> 32);

    // 高64位 = ac + mid的高32位 + mid低32位向高32位的进位
    return ac + (mid >> 32) + ((mid & 0xFFFFFFFF) > (0xFFFFFFFF - (ac & 0xFFFFFFFF)) ? 1 : 0);
}

有符号版本:int64_t imul128hi(int64_t lhs, int64_t rhs)

实现思路

基于无符号乘法结果,结合补码规则修正符号:
有符号数的128位乘积高64位,等于无符号乘积的高64位,加上符号修正项——若lhs为负则减去rhs,若rhs为负则减去lhs(利用补码负数的符号位扩展特性)。

代码实现

int64_t imul128hi(int64_t lhs, int64_t rhs) {
    // 先按无符号计算高64位
    const uint64_t unsigned_result = mul128hi((uint64_t)lhs, (uint64_t)rhs);
    // 符号修正:负数的补码特性,需减去对应操作数
    int64_t result = (int64_t)unsigned_result;
    if (lhs < 0) {
        result -= rhs;
    }
    if (rhs < 0) {
        result -= lhs;
    }
    return result;
}

对应x86-64指令说明

  • imul r8:64位有符号乘法,将rax与r8相乘,结果存入r12:r8(128位),函数返回r12部分。
  • mul r8:64位无符号乘法,将rax与r8相乘,结果存入r12:r8(128位),函数返回r12部分。

内容的提问来源于stack exchange,提问作者l-m

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 16:53:11