2014-09-03 1 views
2

Немного кода, над которым я работаю, меня насторожило. Кажется, я имею дело с переполнением целых чисел, которое, как я признаю, раньше не встречалось, но я пробовал несколько вещей, чтобы исправить это, и никто из них не работал до сих пор. Я использую MSVC++ 2010Целочисленное переполнение, несмотря на достаточно большой тип?

Соответствующий код очень прост, и заключается в следующем:

int64_t numerator = cdfVal * (maxIntensity - 1); 

Это провал для меня в случае, когда cdfVal (это лишь считанное значение из массива , ничего необычного) составляет 8667003, а maxIntensity - 1 - 255. Простой расчет показывает, что решение должно быть 2210085765, тогда как я получаю значение -2084881531. Я понимаю, что это случай целочисленного переполнения, но я думал, что 64 бита будут достаточно большими, чтобы удерживать результат. Я переключился на uint64_t, но в этом случае я получил результат, который составлял двадцать цифр, что явно неверно! Я попытался использовать многозначные целые числа Boost, но получил аналогичные результаты и с этими.

Я чувствую, что это что-то очень просто, что мне не хватает.

+3

какие типы '' cdfVal' и maxIntensity' есть? –

+0

Оба просто нормальные 'int'. – CommanderDJ

+6

'int' *' int' = 'int' –

ответ

3

Тип numerator не имеет отношения к типу, в котором вычисляется выражение. C++ оценивает выражения в «самом большом типе операндов» (без учета некоторых деталей).

Вы упомянули cdfVal и maxIntensity оба типа int. 1 имеет тип int. Это означает, что все выражение оценивается в типе int (и переполняется там). Полученный int затем повышается до int64_t и присваивается numerator.

Если вы хотите обойти это, объявите хотя бы одну из переменных как int64_t, или отбросите хотя бы один из них до нужного типа. Как это:

int64_t numerator = static_cast<int64_t>(cdfVal) * (maxIntensity - 1); 

быть последовательным и немного более ясно, вы, конечно, можете бросить как:

int64_t numerator = static_cast<int64_t>(cdfVal) * static_cast<int64_t>(maxIntensity - 1);