我正在编写自己的小型多精度库,在编写减法方法时,遇到了一些奇怪的错误。这是我为multiprecision减法编写的代码块:
/* subtraction */
for (; p_aReverseIter != a.m_elements.rend(); ++p_aReverseIter, ++p_bReverseIter)
{
temp = static_cast<__int64>(static_cast<__int64>(p_aReverseIter->m_Value) -
static_cast<__int64>(p_bReverseIter->m_Value) +
(carry));
--- debug output-
p_aReverseIter->m_Value = static_cast<unsigned int>(temp & 0xffffffff);
carry = static_cast<unsigned long>(temp >> 32);
}
p_aReverseIter-&gt; m_Value是32位无符号int,而a,b是BigInt。值以Big Endian样式存储在矢量中。 temp是__int64,进位应该是32位无符号长整数。
假设我们从a,a&gt;中减去b。 b(无符号减法),但b中的所有32位字都大于a。此例程生成以下输出:
a = 0xfefefefe (10 elem) 0xfefefefe (10 elem) 0xfefefefe (10 elem)
0xfefefefe (10 elem)
b = 0x12 (2 elem) 0x12121212 (9 elem) 0x12121212 (9 elem) 0x12121212
(9 elem) 0x12121212 (9 elem)
a[i]: 12121212
b[i]: fefefefe
old carry: 0
temp = a - b + carry: ffffffff13131314
Value: 13131314
new carry: ffffffffffffffff
a[i]: 12121212
b[i]: fefefefe
old carry: ffffffff
temp = a - b + carry: 13131313
Value: 13131313
new carry: 0
a[i]: 12121212
b[i]: fefefefe
old carry: 0
temp = a - b + carry: ffffffff13131314
Value: 13131314
new carry: ffffffffffffffff
a[i]: 12121212
b[i]: fefefefe
old carry: ffffffff
temp = a - b + carry: 13131313
Value: 13131313
new carry: 0
...
但进位应始终为0xfffffffff。每次它为零,结果是'13131314'这是错误的。现在让我们将进位从无符号长整齐到无符号__int64和
carry = static_cast<unsigned long>(temp >> 32);
到
carry = static_cast<unsigned __int64>(temp >> 32);
现在始终正确计算进位并设置为0xffffffff。 但正确移位64位的2 ^ 32值应始终产生32位结果。
我的问题是:要了解不同的结果,我缺少什么?
非常感谢你。
答案 0 :(得分:3)
您环境中的sizeof(long)
是什么?我怀疑如果你测试你会发现它是4,即你的unsigned long
实际上是32位值。
答案 1 :(得分:0)
p_aReverseIter->m_Value = static_cast<unsigned int>(temp & 0xffffffff);
carry = static_cast<unsigned long>(temp >> 32);
不要对这些值进行硬编码。您不能保证unsigned long
是任何特定大小(并且它通常不会像您假设的那样是64位)。因此,位移和你的按位'和'必须考虑到这一点。你可以用sizeof(unsigned long)*8
之类的东西替换32。而不是0xffffffff
,~0L
可以做到这一点,或者如果你感到勇敢,可能是-1。 (只要签名的整数由两个补码代表,它就会起作用,通常是的情况,但标准不能保证)