почему это приведет к длинному целочисленному переполнению - PullRequest
19 голосов
/ 14 октября 2011

Я проверил документ, что 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;

Это работаетхорошо.

Ответы [ 5 ]

48 голосов
/ 14 октября 2011

Проблема в том, что литерал "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

5 голосов
/ 14 октября 2011

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

long r = 99;
long test1 = r*r*r*r*r;
4 голосов
/ 14 октября 2011

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

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

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

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

3 голосов
/ 14 октября 2011

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

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

Подробнее см. В документации MSDN .

1 голос
/ 14 октября 2011

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

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

long test2 = 99L*99L*99L*99L*99L;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...