不同的32bit-cast成长/ __ int64,为什么?

时间:2009-11-27 13:26:25

标签: c++ bignum

我正在编写自己的小型多精度库,在编写减法方法时,遇到了一些奇怪的错误。这是我为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位结果。

我的问题是:要了解不同的结果,我缺少什么?

非常感谢你。

2 个答案:

答案 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。 (只要签名的整数由两个补码代表,它就会起作用,通常是的情况,但标准不能保证)