一对uint64值的长乘法

问题描述

如何安全地将一对uint64值相乘以得到一对相同类型的LSB和MSB?

typedef struct uint128 {
    uint64 lsb;
    uint64 msb;
};

uint128 mul(uint64 x,uint64 y)
{
    uint128 z = {0,0};
    z.lsb = x * y;
    if (z.lsb / x != y)
    {
        z.msb = ?
    }
    return z;
}
  1. 我可以正确计算LSB吗?
  2. 如何正确计算MSB?

谢谢!

解决方法

如评论中所述,最好的解决方案可能是使用为您执行此操作的库。但是我将解释没有图书馆怎么办,因为我认为您要求学习一些东西。这可能不是一种非常有效的方法,但是它可以工作。

当我们在学校里并且必须在没有计算器的情况下将2个数字相乘时,我们将2个数字相乘,结果得到1-2个数字,并将其写下来,最后我们将它们加起来。我们把乘法加起来,所以我们只需要一次计算一位数乘法。如果CPU上的数字更大,则可能发生类似的情况。但是这里我们不使用十进制数字,而是使用寄存器大小的一半作为数字。这样一来,我们就可以在一个寄存器中将2位数字乘以2位。十进制13 * 42可以计算为:

  3* 2 =     0 6
 10* 2 =     2 0
  3*40 =   1 2 0
 10*40 = 0 4 0 0
        --------
         0 5 4 6

使用整数可以完成类似的操作。为简单起见,我将2个8位数字乘以8位CPU上的16位数字,因为我一次只能将4位乘以4位。让我们将0x73与0x4F相乘。

0x03*0x0F = 0x002D
0x70*0x0F = 0x0690 
0x03*0x40 = 0x00C0 
0x70*0x40 = 0x1C00
            -------
            0x22BD

您基本上创建了一个由4个元素组成的数组,在这种情况下,每个元素的类型均为uint32_t,如果结果为,则将单个乘法的结果存储或添加到数组的正确元素中。单个乘法对于单个元素而言太大,请将较高的位存储在较高的元素中。如果加法溢出,则将1携带到下一个元素。最后,您可以将数组的2个元素组合在一起,在您的情况下可以合并为两个uint64_t

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...