假设我只有16位变量可用。如何计算需要32位存储结果的这两个整数的乘积?
答案 0 :(得分:3)
std::uint16_t v0 = /* whatever */;
std::uint16_t v1 = /* whatever */;
std::uint16_t r0, r1;
r0 = (v0 & 0xFF) * (v1 & 0xFF);
r1 = (v0 >> 8) * (v1 >> 8);
std::uint16_t temp = (v0 & 0xFF) * (v1 >> 8);
r0 += temp << 8;
r1 += temp & 0xFF;
temp = (v1 & 0xFF) * (v0 >> 8);
r1 += temp << 8;
r0 += temp & 0xFF;
注意:书面但未经过测试。我们的想法是将每个数字分成两个8位部分,计算出四个交叉乘积,然后将它们相加,形成一个32位结果,存储为两个16位部分。
答案 1 :(得分:1)
您可以使用字符串或字符数组来执行此操作。以下是一些有用的链接:
Addition-Multiplication-of-Very-Long-Integers
答案 2 :(得分:1)
您几乎肯定会不想要存储单个十进制数字来执行此操作。那是非常低效的。
仍然合理有效的最简单方法是移位和添加算法。汇编语言比C或C ++更容易(因为你可以直接使用进位标志),但你也可以用更高级的语言来完成。
这是x86汇编语言的版本。此特定版本执行32x32位乘法以获得64位结果。将其更改为16x16以获得32位结果主要是将eax
更改为ax
,ebx
更改为bx
等等。
mult proc
; multiplies eax by ebx and places result in edx:ecx
xor ecx, ecx
xor edx, edx
mul1:
test ebx, 1
jz mul2
add ecx, eax
adc edx, 0
mul2:
shr ebx, 1
shl eax, 1
test ebx, ebx
jnz mul1
done:
ret
mult endp
C或C ++中的相同算法执行起来有点复杂,因为我们没有进位来告诉我们何时操作溢出并且我们需要从操作数的低位字执行位上层。在C或C ++中使用最简单(尽管不是最有效)的方法是每个操作数只使用15位,因此我们需要3个字来获得32位结果。例如,add
之前的adc
/ mul2
通过添加低位字来进行双字添加,然后将进位位添加到高位字。由于缺少进位,我们可以添加低位字,然后or
和0x8000
来隔离最高位。然后将其添加到较高的单词,并将其屏蔽在较低的单词(and
上~0x8000
)上。
幸运的是,在这种情况下,您的输入操作数确实适合单个变量,因此您不必处理“桥接”单词之间的转换。