Подтвердить что ты не робот

Почему это приведет к длительному переполнению целого числа

Я проверил документ, что long= int64 имеет диапазон более 900 000 000 000 000

Вот мой код:

int r = 99;
long test1 = r*r*r*r*r;

во время выполнения он дает мне 919 965 907 вместо правильных 9,509,900,499.

другой тест

long test2 = 99*99*99*99*99;

Он отказывается компилировать, говоря о переполнении целых чисел.

Но если я делаю это

long test3 = 10100200300;

Это отлично работает.

4b9b3361

Ответ 1

Проблема заключается в том, что буква "99" обрабатывается как int. Если вы добавите "L", он будет считать его длинным. Чтобы устранить проблему с компиляцией, выполните следующие действия.

long test2 = 99L * 99L * 99L * 99L * 99L;

И исправить "неправильный результат", вызванный переполнением целых чисел:

long r = 99;
long test1 = r * r * r * r * r;

Ключевым моментом является то, что выражение справа от "=" оценивается до того, как выполняется присвоение long r.

Существуют и другие буквенные суффиксы, которые могут вас заинтересовать:

Type    Suffix    Example
uint    U or u    100U
long    L or l    100L
ulong   UL or ul  100UL
float   F or f    123.45F
decimal M or m    123.45M

@m.edmonson, касающийся вашего вопроса о том, почему это выходит на 919965907. Что происходит, это то, что значение "обертывание" вокруг int.MaxValue. Вы можете увидеть это с помощью небольшой тестовой программы:

int i = 99; // 99
i *= 99;    // 9801
i *= 99;    // 970299
i *= 99;    // 96059601
i *= 99;    // 919965907        should be 9509900499 but comes out to 919965907
            //                      which is (9509900499 % int.MaxValue)

long k = 9509900499 % int.MaxValue;

Что означает "обертывание"? Когда вы превысите int.MaxValue на 1, значение "возвращается" на int.MinValue.

int j = int.MaxValue;
j++;

bool isNowMinValue = (j == int.MinValue);   // true, the value has "wrapped around"

Это немного упрощенно; если вы ищете "целочисленное переполнение", вы получите лучшее объяснение. Стоит понять, как целые числа (и другие числовые типы) представлены 32 битами:

http://en.wikipedia.org/wiki/Signed_number_representations

Ответ 2

Он использует целочисленное умножение:

long r = 99;
long test1 = r*r*r*r*r;

Ответ 3

Как сказал другой, но:

long test2 = 99L * 99 * 99 * 99 * 99;

Это даст вам правильный результат с меньшим L вокруг: -)

Это происходит потому, что первый 99L является long, поэтому все умножения выполняются в поле long ", а все остальные целые числа повышаются до long до умножения (очевидно, умножение всегда между 2 числа и слева направо, так что ((99L * 99) * 99) * 99) * 99, и каждый" частичный" результат длинный и приводит к тому, что следующий операнд будет преобразован в длинный.)

Ответ 4

Второй тест терпит неудачу, потому что каждый 99 является целым числом; замените его следующим и компилируется.

long test2 = 99L * 99L * 99L * 99L * 99L;

Подробнее см. MSDN Long Documentation.

Ответ 5

Компилятор рассматривает 99 как целые числа, хотя конечный результат будет длинным.

Это будет работать.

long test2 = 99L*99L*99L*99L*99L;