Я пишу свою маленькую мультиточную библиотеку, и при написании метода вычитания я столкнулся с какой-то странной ошибкой. Вот блок кода, который я написал для вычитания с множественной точностью:
/* 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-битный без знака.
Допустим, мы вычитаем b из a, a > b (беззнаковое вычитание), но все 32-битные слова в b больше, чем 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
...
Но перенос всегда должен быть 0xffffffffff. Каждый раз, когда он равен нулю, результат равен «13131314», что неверно. Теперь давайте изменим перенос с unsigned long на unsigned __int64 и
carry = static_cast<unsigned long>(temp >> 32);
to
carry = static_cast<unsigned __int64>(temp >> 32);
Теперь перенос всегда рассчитывается правильно и равен 0xffffffff. Но сдвиг вправо 64-битного значения 2^32 всегда должен давать 32-битный результат.
Мой вопрос: чтобы понять разные результаты, что мне не хватает?
Большое тебе спасибо.
long long
также не является стандартным в С++. Он определен в C++99 и планируется добавить в C++ в C++0x, но его пока нет. - person jalf   schedule 27.11.2009