我想使用 Excel 将 32 位整数相乘并得到低 32 位。换句话说,给定数字 n1、n2,我想计算MOD(n1*n2, 2^32)
。但是,此公式在 Excel 中不起作用,因为(对于较大的 n1 和 n2),乘积超出了 Excel 的精度容量,因此会舍去低位数字。有什么方法可以让我避免这种情况,同时仍然使用 Excel?
我想到的一个原始解决方案就是将其中一个数字分成 8 位块并进行相应的相乘(MOD
必要时使用截断),但我正在寻找一些不那么混乱的东西,希望如此。
答案1
如果你使用的是 64 位 Office,那么你可以创建自定义函数并使用新的LongLong
类型进行计算。按Alt+F11打开 Visual Basic 编辑器,单击插入 > 模块然后粘贴以下代码
Public Function MulMod32(number1, number2) As Double
Dim n1 As LongLong, n2 As LongLong
n1 = CLngLng(number1)
n2 = CLngLng(number2)
' Sign-extend the numbers
n1 = IIf((n1 And &H80000000&) = 0, n1, n1 Or &HFFFFFFFF00000000^)
n2 = IIf((n2 And &H80000000&) = 0, n2, n2 Or &HFFFFFFFF00000000^)
MulMod32 = CDbl((n1 * n2) And &HFFFFFFFF^)
End Function
之后你可以MulMod32()
在任何公式中使用,例如=MulMod32(HEX2DEC("fffffffe"), HEX2DEC("ffff1234"))
如果没有,LongLong
那么你可以将数字拆分成更小的部分进行操作,但你不需要处理 8 位块,因为 16 位值就足够了。如果我们有 a 和 b,那么将它们拆分为 (ah, al) 和 (bh, bl) 后,它们的乘积可以像这样计算
a × b = (ah × 2 16 + al)(bh × 2 16 + bl) = ah × bh × 2 32 + (ah × bl + al × bh) × 2 16 + al × bl
因此,我们可以有 4 列 ah、al、bh、bl 和 1 列乘积,其公式如下
A1 | B1 |
---|---|
啊 | =BITRSHIFT(a,16) |
艾尔 | =BITAND(a,65535) |
対象 | =BITRSHIFT(b,16) |
bl | =BITAND(b,65535) |
产品 | =BITAND(BITAND((ah*bl + bh*al), 65535)*2^16 + al*bl, 4294967295) |
答案2
如果你看看规格和限制您会发现至少自 Excel 2007 以来就存在以下限制:
特征 最大限制 数字精度 15 位数字 允许的最小负数 -2.2251E-308 允许的最小正数 2.2251E-308 允许的最大正数 9.99999999999999E+307 允许的最大负数 -9.99999999999999E+307 通过公式得出最大允许正数 1.7976931348623158e+308 通过公式得出最大允许负数 -1.7976931348623158e+308
正如您所看到的,根据您使用的数字,您将不可避免地会失去精度。
由于您指定了 32 位数字(假设为无符号整数),因此需要计算的最大值将是 18,446,744,073,709,551,616(2 32 *2 32 = 2 64),这显然超过了 15 位数字的限制,尽管它没有超过可以计算的最大数字的限制。
此外,如果您计划获取结果的低 32 位,那么最好采用实际的编程或脚本语言来进行这样的计算。
答案3
我想到的一个原始解决方案就是将其中一个数字分成 8 位块并进行相应的相乘(必要时使用 MOD 进行截断),但我正在寻找一些不那么混乱的东西,希望如此。