【问题标题】:128-bit integer multiplication128 位整数乘法
【发布时间】:2026-02-16 04:10:01
【问题描述】:

我在大学的任务是用 C 语言计算 2 个 128 位整数的乘积并返回旧的 64 位。随意使用下面的代码打印出 128 位整数乘积的低 128 位。

更新!!!

我的老师突然说他打算打印旧的 64 位。我决定使用char * 存储所有 128 位并将乘法结果打印为 128 个低位。下面的代码有效:

        #include <stdio.h>
        #include <stdlib.h>

        char *moveBit(char *s){ // moves the binary string one bit to the left (like s<<1 operation)
            char bit='0';
            char temp='0';
            for(int i=127;i>=0;i--){
                temp = s[i];
                s[i]=bit;
                bit=temp;
            }
            return s;
        }

        char *bitSum(char *a, char *b){ // figures out the sum of two numbers bit by bit

            char rem = '0';
            char* sum = (char *) malloc(129);

            for(int i=127;i>=0;i--){

                int s = (a[i]=='1') + (b[i]=='1') + (rem=='1');

                if (s==3){
                    sum[i]='1';
                    rem='1';
                }else if(s==2){
                    sum[i]='0';
                    rem='1';
                }else{
                    sum[i] = s? '1':'0';
                    rem='0';
                }
            }

            return sum; 
        }

        char *mult(char *a, char *b){

            char* product = (char *) malloc(129);

            for(int i=127;i>=0;i--){

                if(b[i]=='1')
                    product = bitSum(product,a);
                a=moveBit(a);

            }
            return product; 
        }

        int main(){

            char *a = (char *) malloc(129);
            char *b = (char *) malloc(129);

            a="01111111111111111111111111111111101010001101100110100000011111111111111111111111111111111111111111111111111110111111001111111111";
            b="01111111111111111111111111111111111111111111110111111001111111111111111111111111111111111111111111111111111111011111100111111111";

            printf("%s", mult(a,b));
            return 0;
        }

【问题讨论】:

  • 你确定它们是指“最后”的最低 64 位吗?这将使它成为一个微不足道的问题(只需将低部分乘以uint64_t)。我会认为大部分时间都是“第一”部分。
  • 在实际情况下,您将使用en.wikipedia.org/wiki/GNU_Multiple_Precision_Arithmetic_Library。然而这是家庭作业,所以你需要自己做——作弊会让你被开除。
  • 如果你倾倒除了 l.s. 之外的所有东西。那么你需要使用无符号。
  • 如果你定义了一个掩码,你的代码使用long long int cutter = 0x7fffffffffffffffLL会更易读
  • 也许您应该将每个 64 位被乘数分解为两个 32 位部分(在丢弃 128 位输入的高 64 位之后,这似乎无关紧要) ,然后“手动”进行长乘法。也就是说,计算四个 32×32 到 64 位的乘积,并弄清楚如何将它们重新组合成您需要的结果。 (提示:其中一种产品可以扔掉。)

标签: c performance memory


【解决方案1】:

long long 在我使用过的任何计算机上都不是 128 位类型。请参阅下面的参考资料。我还假设“最后一位”是指“高位”。此代码将用于在 GCC 上进行无符号 128 位运算(调整编译器的类型名称):

#include <stdint.h>
#include <stdio.h>

int main () {
        __uint128_t x = 9223372036146775308;
        __uint128_t y = 9223372036854709503;
        __uint128_t prod = x * y;
        uint64_t high = prod >> 64;

        printf("%lu\n", high);
}

我的机器上的类型有多长?

窗户: https://msdn.microsoft.com/en-us/library/94z15h2c.aspx

Linux、Mac OSX、“所有其他系统”: 第 13 页,http://www.x86-64.org/documentation/abi.pdf

【讨论】:

  • long 不是 64 位类型,尽管它可能是。它保证至少是 32 位,它在我的 MSVC 编译器上。您的 MS 链接显示 4 个字节。
  • 另外,类型宽度不依赖于编译器,这是一个神话。类型宽度在系统 ABI 中定义。否则使用不同工具编译的库和程序将无法互操作。
  • 代码可以使用更便携的便携式printf("%" PRIu64, high);printf("%llu\n", (unsigned long long) high); OTOH,这个解决方案确实依赖于__uint128_t 现有的。