Проблема с целочисленным преобразованием

int left = std::numeric_limits<int>::min();
int right = -1;
//the code below instead of give one more than int_max gives: 18446744071562067968
unsigned long long result = left * right;

Я пытался найти UAC, но даже в соответствии с правилами UAC это должно давать правильный вывод. Есть идеи, почему результат неверен?

0

Решение

Это неопределенное поведение, чтобы умножить минимальное значение дополнения со знаком 2 int на -1, потому что результат находится за пределами диапазона типа.

В этом случае ваш вывод соответствует результату -2147483648, т. Е. Переполнение, похоже, обернулось вокруг. Вы не можете полагаться на перенос для подписанных типов, только для неподписанных типов.

Присвоение результата расчета unsigned long long не меняет тип, в котором выполняется вычисление. Как только вы сделаете умножение, вы проиграете. Итак, преобразовать один из операндов в unsigned long long до множатся.

4

Другие решения

Оба операнда int, поэтому арифметика выполняется в пределах int тип; результат операции выходит за пределы диапазона int, так что результат не определен.

Чтобы получить ожидаемый результат, приведите один операнд к long long первый:

 unsigned long long result = left * (long long) right;

Это все еще потенциально неопределенное поведение; безопаснее преобразовать в беззнаковую арифметику как можно раньше (поскольку арифметика без знака переносится и не переполняется):

unsigned long long result = left * (unsigned long long) right;

Обратите внимание, что результат, к которому вы пришли, 0xffffffff80000000; это указывает на то, что фактический результат операции был std::numeric_limits<int>::min() в int тип, который затем был расширен знак и приведен к unsigned long long,

4

Причина в том, что умножение совершается с точки зрения int,

Оба аргумента int, так что умножение дает int Agein, и вы были правы, это дает int_max +1, что эквивалентно int_min= -2147483648. Так что на самом деле это -2147483648, но для длинных без знака он эквивалентен 18446744071562067968, см. Шестнадцатеричные коды:

                       int_min =         80000000
(unsigned long long) (int min) = ffffffff80000000
0
По вопросам рекламы [email protected]