числа с плавающей запятой в c [Xcode IDE] - PullRequest
1 голос
/ 22 апреля 2011

Я начал изучать язык c, но проблема в том, что я не понимаю, как использовать числа с плавающей запятой. Я использую Xcode в качестве IDE. Вот результаты, которые запутали меня:

float x1 = 1.123456789123456789f;  
double x2 = 1.123456789123456789f;  
float x3 = 987654321.123456789f;  
double x4 = 987654321.123456789f;  

printf("x1 = %.20f\n", x1);  
printf("x2 = %.20f\n", x2);  
printf("x3 = %10.10f\n", x3);  
printf("x4 = %10.10f\n", x4);  

Вывод:

x1 = 1.12345683574676513672  
x2 = 1.12345683574676513672  
x3 = 987654336.0000000000  
x4 = 987654336.0000000000  

Вопрос в том, почему x1, x2 теряют свои числа с плавающей запятой после 1.12345678? А почему x3 и x4 усекаются?

Ответы [ 2 ]

4 голосов
/ 22 апреля 2011

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

double должно иметь возможность хранить примерно вдвое больше цифркак float, но все ваши литералы с плавающей точкой являются float литералами.Удалите постфикс f в строках double, чтобы фактически использовать все биты, доступные для double.

1 голос
/ 22 апреля 2011

Чего вам не хватает, так это того, что вы переводите каждое из ваших чисел в 2 базовые преобразования, а в x2 и x4 - в расширяющееся преобразование типов.

Прежде всего, у вас есть десятичные литералы, которыеКомпилятор преобразует в двоичные дроби типа float, которые имеют точность 23 двоичных разряда (что эквивалентно примерно 7,2 десятичных цифр) и не могут точно представлять большинство десятичных дробей, даже те, которые соответствуют их точности.Затем x2 и x4 присваиваются double переменным, но поскольку все, что не умещается в 23 двоичные цифры, уже обрезано, они магическим образом не восстанавливают точность, которая присутствовала в литералах.

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

Это в основном то же самое, что если вы попытаетесь преобразовать 1/3 в десятичную дробь 0,333 и обратно в правильную дробь 333/1000 - эй, а почему не 1/3?

Прочитайте справочник с плавающей точкой для получения дополнительной информации.

...