【问题标题】:Multiplying two 128-bit ints将两个 128 位整数相乘
【发布时间】:2014-02-28 03:19:11
【问题描述】:

我正在尝试在 C 中将两个 128 位整数相乘。

这是我的算法:

将两个 128 位序列拆分为 S1 和 S2。

然后将 S1 拆分为 S11(前/上半部分)和 S12(后/下半部分),并将 S2 拆分为 S21(前/上半部分)和 S22(后/下半部分)。

将 S12 乘以 S22... = S1222。

将 S11 乘以 S21... = S1121,然后将其乘以 2^128 进行位移

将 S1222 和 S1121 组合为新阵列的前半部分和后半部分。我们称它为“Array1”。新数组的长度是 S1 的两倍。

然后我们必须将 S12 乘以 S21 和 S11 乘以 S22。我将这两者相乘,分别得到 S1221 和 S1122(并相应地对它们进行了位移)。现在我必须将它们添加到 Array1。这是我寻求帮助的部分。我不确定如何将这些一一添加到 Array1。请记住,当您从 Array1 的 3/4 到 Array1 的 1/4 时,可能会有进位 1,因为这是需要添加 S1221 和 S1122 的跨度。

我的问题是:如何将 dstM1 和 dstM2 添加到已经填充的数组 d 中?

【问题讨论】:

  • ...你的问题是?
  • 如何将dstM1和dstM2添加到已经填充的数组d中。
  • 为什么要努力使用uint32_tuint64_t,然后使用具有0xffffffffu 等值的unsigned 数组[4]。 unsigned 仅保证范围为 0 到 65535。如果您想使用 unsigned,1) 准备好变体大小,2) 假设最小 C 规范范围或 3) 只需使用 uint32_t。跨度>
  • 将 a[0..n] 解释为 a[0]*2^32n + a[1]*2^32(n-1) + a[2 不是更容易吗? ]*2^32(n-2) + .. + a[n-1]*2^32 + a[n]*2^0 这就是我们对待小数位的方式。
  • 请注意,您可以使用Karatsuba trick 将每个子问题的递归乘法数从 4 降低到 3

标签: c integer-arithmetic


【解决方案1】:

如果您使用 gcc 或 clang,您可以直接使用 __int128unsigned __int128

【讨论】:

  • 我想在没有这些的情况下将两个整数相乘。我想使用如上所述的分而治之算法。
  • 如果不使用那些编译器,那会怎样?
  • 我的意思是不使用“那些”,“那些”是 _int128 和未签名的 _int128。
  • @thetypist 这是有道理的。不过,您可能希望在直接汇编程序中执行此操作,因为您可以直接访问溢出寄存器。
【解决方案2】:

您陷入了无限循环,因为i += 1/32i += 0 相同。

另外:注意:memcpy(&d[3l/2-i], dstM1, 1/8);memcpy(&d[1-i], dstM1, 0);

【讨论】:

    【解决方案3】:

    总结您的问题:如何添加两个传播进位的(无符号)整数数组。

    uint16_t foo[4];  // 0000 aaaa FFFF cccc
    uint16_t bar[4];  // dddd eeee FFFF 0000
    

    好的一点是'FFFF+FFFF+1'就是(1)FFFF。因此,进位总是可以添加到每个单词中,而不会产生额外的进位(好像总和可以是 20000)。

    临时求和:sum = foo[3] + bar[3] + carry;,进位最初为 0,此求和是否产生新的进位。

    • 如果(A+B) < A,则从 (A+B) 生成进位
    • 求和 (A+B+c) 时,如果 ((A + c) < A) || (((A + c) + B) < B) 产生进位

    另一种可能性是通过将列中的几个项相加来计算“多位进位”,这通常发生在 bignum 乘法中:

                AAAA BBBB CCCC
           DDDD EEEE FFFF ....
      GGGG HHHH IIII .... ....
    --------------------------
      col4 col3 col2 col1 col0
    

    现在每一列都会产生 32 位或 64 位结果和一个不一定适合单个位的进位。

    uint32_t sum_low = carry_in_from_previous_column;
    uint32_t sum_high = 0;
    
    for (i = 0; i < N; i++) {
         sum_low += matrix[i][column] & 0xffff;
         sum_high += matrix[i][column] >> 16;
    }
    sum_high += sum_low >> 16;    // add the multibit half carry
    
    result = (sum_low & 0xffff) | (sum_high << 16);
    carry_out = sum_high >> 16;
    

    【讨论】:

    • 修正了公式。 (A+c) 仅在 c=1 且 A=FFFF 时产生进位;那么结果是'0',但这不是充分条件。
    猜你喜欢
    • 2015-11-28
    • 2015-10-17
    • 2011-05-26
    • 1970-01-01
    • 2017-04-09
    • 2019-03-15
    • 2013-12-12
    • 1970-01-01
    • 2012-03-16
    相关资源
    最近更新 更多