Тип продвижение и конвертация в с

double dVal;
int iVal = -7;
unsigned long ulVal = 1000;
dVal = iVal * ulVal;
printf("iVal * ulVal = %lf\n", dVal);

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

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

0

Решение

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

iVal повышен с int до unsigned long. Таким образом, его значение -7 (комплимент для двоих) становится положительным значением 0xFFFFFFF9 (т. Е. 4294967289) (по крайней мере, в вашей конкретной системе).

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

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

0

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

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

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

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

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

Если типы после продвижения одинаковы, этот тип является общим типом

Это не применимо, так как типы являются int и unsigned long соответственно.

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

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

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

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

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

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

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector