2016-10-07 2 views
0
double dVal; 
int iVal = -7; 
unsigned long ulVal = 1000; 
dVal = iVal * ulVal; 
printf("iVal * ulVal = %lf\n", dVal); 

Может кто-нибудь объяснить шаг за шагом, как получить 4294960296.000000?Продвижение и преобразование типа в c

  • Что приходит первым, меняя знак Ival для знака или продвижения типу ulVal перед тем умножения с ulVal?
  • Также, если мы умножим iVal и ulVal, мы вышли из диапазона для длинного типа , и мы сохраним это значение умножения на двойную переменную (так что мы снова имеем преобразование ). Но как мы можем знать, к какому значению нужно округлить, когда двойной тип является самым точным вокруг 0, и как далеко мы переходим от 0, расстояние между соседними номерами больше?
+0

[Эта скрытая ссылка на конверсии] (http://en.cppreference.com/w/c/language/conversion) может пригодиться. –

ответ

1

Это действительно довольно просто:

Ival стимулируется от ИНТ до неподписанных долго. Таким образом, его значение -7 (будучи дополнением двух) становится положительным значением 0xFFFFFFF9 (то есть 4294967289) (по крайней мере, на вашей конкретной системе).

Это при умножении на 1000 переполняет unsigned long, поэтому вместо того, чтобы быть результатом 4 294 967 289 000 (0x3E7 FFFF E4A8), он заканчивается 0xFFFFE4A8 (429960296).

Затем оно преобразуется в двойное, получая окончательный ответ. Конечные нули - это потому, что значение поплавка очень немного выше 429960296, потому что оно построено как сумма фракций, которые printf округляется до 6 цифр.

+0

Убрать ответ, спасибо! – Lazar

1

Ссылаясь на http://en.cppreference.com/w/c/language/conversion как было упомянуто Joachim,

Сначала умножение двух целых чисел происходит. Затем результат сохраняется в поплавке.

Итак, мы смотрим на iVal * ulVal. Здесь мы ссылаемся на раздел на Обычные арифметические преобразования. Оба операнда являются целыми числами, поэтому применяется случай 4..

Сначала целые рекламные акции. В этом оба операнда являются ints или больше, поэтому они не изменяются.

Если типы после продвижения те же, что тип является распространенным типом

Это не применимо, так как типы INT и без знака длиной соответственно.

В противном случае, если оба операнда после продвижения имеет одинаковую знаковость (подписанный или оба знака), операнд с меньшим рангом преобразования (см ниже) неявно преобразуется к типу операнда с большим рангом преобразования

Это тоже не применяется, так как подписан один тип, а второй является беззнаковое

в противном случае, знаковость отличается: Если операнд с неподписанных типа имеет преобразование ранг больше или равен ранг типа подписанный операнд, то операнд с знаковым типом неявно преобразуется в беззнаковый тип

Здесь без знака операнд длинный и подписанный является ИНТОМ ранга долго больше междунара, поэтому применяется эта часть. Подписанный int преобразуется в unsigned long.

Итак, у нас есть умножение двух чисел 4294967289 (без знака длиной) и 1000 (без знака длинный). При выполнении умножения происходит переполнение, но если вы вычислите 4294967289000 % 2^32, вы получите 4294960296.

Затем оно преобразуется в поплавок на знак равенства и затем печатается.

Смежные вопросы