Почему 215510 * 10000! = 2155100000? [Дубликат]

0

У меня есть следующий код:

UINT64 time1 = 215510*10000;
UINT64 time2 = (UINT64)(215510 * 10000);

При печати или в режиме "Watch" получается:

time1 = 18446744071569684320
time2 = 18446744071569684320

На самом деле я знаю, как сделать это прямо здесь. Для получения правильного ответа мы должны использовать один из следующих кодов (следующие 3 версии все в порядке):

UINT64 time3 = (UINT64)215510 * 10000;
UINT64 time4 = 215510 * (UINT64)10000;
UINT64 time5 = (UINT64)215510 * (UINT64)10000;

Но почему первые две строки не могут дать правильный ответ?

  • 2
    @JohnZwinck: Нет, это не дубликат. Другой вопрос касается арифметики с плавающей точкой; это чисто целочисленная арифметика.
  • 1
    215510*10000 - это int потому что оба операнда являются int .
Теги:

3 ответа

9
Лучший ответ

Поскольку литеральная константа, как 215510, как правило, int (не long) в стандарте C++. Он не связан с Visual Studio (он должен быть таким же с другим компилятором, как GCC, ака g++ по крайней мере, если int имеет 32 бита), поэтому 215510 * 10000 также является int. Попробуйте 215510L * 10000 чтобы иметь один множитель и быть long (следовательно, продукт также будет long - это не изменит продукт, если он еще long 32 бита!) Или даже 215510LL чтобы сделать его long long или с явным литом (int64_t)215510...

И на вашей платформе int, вероятно, 32 бита. Таким образом, подписанный INT_MAX составляет 2147483647 (что составляет 2 31 - 1).

И Кейт Томпсон справедливо прокомментировал это

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

per (стандарт C11 §6.4.4.1, пункт 5 или) C++ 11 стандарт §2.14.2, пункт 2. Таким образом, реализация с 16 битами int и long 32 бит 215510 является long константой литерала (поскольку 215510> 32767, которая будет его INT_MAX....).

Так что, вопреки тому, что я считаю, тип литеральной интегральной константы не определяется суффиксом -or недостатком it-, но и его значением!

  • 1
    215510 имеет тип int только в том случае, если int достаточно велик для его хранения. int может быть как 16 битов, что делает INT_MAX 32767; в такой системе 215510 будет иметь тип long .
  • 0
    Если long также имеет 32 бита, этот ответ не будет полезен. И согласно документации , это так.
Показать ещё 6 комментариев
11

Это связано с тем, что вы вызываете переполнение целых чисел путем умножения двух 32-разрядных чисел, результат которых превышает 32 бита. Сначала вам нужно преобразовать в 64 бита, как вы уже показали.

3

В C++ недопустимый целочисленный литерал имеет тип int, long int или long long int, в зависимости от того, какой из них является первым, в котором может быть представлено его значение. (long long int был относительно недавним дополнением к языку).

Вероятно, в вашей системе 215510 и 10000 имеют тип int, который, вероятно, является 32-битным типом.

Выражения (обычно) оцениваются сами по себе, независимо от контекста, в котором они появляются. Таким образом, выражение 215510*10000 оценивается как int. Поскольку математический результат превышает INT_MAX, результат не определен, но он, вероятно, будет -2139867296.

Когда это значение преобразуется в 64-разрядный неподписанный тип, он обтекает, получая 18446744071569684320 (что немного меньше 2 64).

  • 0
    Буквальная константа 215510 всегда является int (это не система конкретным, требуются по стандарту).
  • 0
    @BasileStarynkevitch: это неправильно. Я предлагаю вам проверить свои источники. Цитируя стандарт ISO C ++ 2003, 2.13.1p2: «Тип целочисленного литерала зависит от его формы, значения и суффикса. Если он десятичный и не имеет суффикса, он имеет первый из этих типов, в котором его значение может быть представленный: int , long int ; если значение не может быть представлено как long int , поведение не определено. " Стандарт 2011 добавляет long long int и показывает правила в таблице.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню