Неправильный результат выводится при умножении чисел в C - PullRequest
1 голос
/ 18 сентября 2011

Я недавно начал использовать C, и у меня возникли некоторые проблемы с простой арифметической операцией, состоящей в умножении двух чисел.

Изначально я пытался напечатать результат 8 * 2 в файл. В настоящее время это выводит 16. Затем я умножил то, что я действительно хотел, 8 * 0,000000123456789. Вот мой код:

            fprintf( fp2, "%d\n", (long double)(8*0.000000123456789));

Результат, выведенный в файл: -1086490624 . Тогда как на самом деле это должно было быть: 0.000000987654312 . Я намеренно набрал арифметику как длинный дубль, чтобы избежать переполнения. Ничего не делать и использовать:

            fprintf( fp2, "%d\n", (8*0.000000123456789));

Доходность 1719134127 , опять-таки не имеющая никакого отношения к фактическому значению 0,000000987654312

Есть предложения, пожалуйста?

Ответы [ 2 ]

8 голосов
/ 18 сентября 2011

Предложение 1: Прочтите руководство для printf.

Предложение 2: Повторяйте себе снова и снова: " printf небезопасен. Я обещаю быть очень осторожным при использованииit. "

Предложение 3: Всегда всегда включайте и принимайте близко к сердцу все предупреждения компилятора.Это сразу поймало бы.

Ответ: Вы обещаете printf, что вы предоставите int, сказав %d.Однако на самом деле вы предоставляете long double.Результатом этого невыполнения обещания является неопределенное поведение .Чтобы напечатать длинный двойной, скажем %Lf (ср. (1)).

8 голосов
/ 18 сентября 2011

Я считаю, что ваша проблема в том, что вы используете заполнитель %d в printf, который печатает только значения int. Поскольку вы передаете double или long double в printf, вы, вероятно, захотите использовать другой модификатор вместо %d. Например, если вы печатаете double, вы можете использовать модификатор %f:

fprintf( fp2, "%f\n", (8*0.000000123456789));

Более техническая причина, по которой вы возвращаете случайные значения вместо чего-либо, близкого к исходному значению, заключается в том, что когда вы пытаетесь распечатать что-то с помощью printf, функция пытается интерпретировать биты аргумента таким образом, который зависит от какой спецификатор вы используете. Поскольку значения с плавающей точкой, такие как float s и double s, обычно представляются внутри компьютера с использованием совершенно иной кодировки, чем целые числа (часто в виде значений IEEE-754 вместо дополнения до двух со знаком) ), результаты попытки получить биты float или double и представить их как целое число обычно бессмысленны.

Надеюсь, это поможет!

...