【发布时间】:2010-12-20 23:52:20
【问题描述】:
我正在编写自己的小型多精度库,在编写减法方法时,遇到了一些奇怪的错误。这是我为多精度减法编写的代码块:
/* 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->m_Value 是 32 位无符号整数,而 a,b 是 BigInt。值以 Big Endian 样式存储在向量中。 temp 是 __int64 并且进位应该作为 32 位无符号长。
假设我们从 a 中减去 b,a > 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',这是错误的。现在让我们将进位从 unsigned long 更改为 unsigned __int64 和
carry = static_cast<unsigned long>(temp >> 32);
到
carry = static_cast<unsigned __int64>(temp >> 32);
现在进位总是正确计算并设置为 0xffffffff。 但是将 2^32 的 64 位值右移应该总是产生 32 位的结果。
我的问题是:要了解不同的结果,我缺少什么?
非常感谢。
【问题讨论】:
-
小注:可以使用标准的long long代替非标准的__int64
-
long long在 C++ 中也不是标准的。它是在C++99中定义的,计划在C++0x中添加到C++中,但目前还没有。 -
@Zyrkon:抱歉,您的描述毫无意义。如果我们正在执行无符号减法和 A > B,如您所说,B 中的所有单词不能大于 A 中的所有单词。此外,在您的示例中,您的逐个元素数据与数组数据(A 和B交换)。请先把事情整理好,然后我们才能开始理解这一切。
-
这应该是以社区wiki为例,如何不使用c++。关于您的问题,不要混合使用 __int64、long 和 int。如果您需要具有精确定义宽度的类型,请因此使用 __int64(或更好的来自外部 stdint.h 的 uin64_t,这在 vc++ 上是缺失的)并完全避免使用 long 甚至 unsigned int。