Преобразует строку в двойную, равную буквальному двойнику?
Например:
assert(atof("1.2") == 1.2);
независимо от того, какой тип float используется?
Я понимаю, что точность с плавающей запятой не является точной, но она точно неточна, и округление к двоичному образует то же самое двойное?
Ответы
Ответ 1
Это не гарантируется стандартом C. Семантика преобразования литерала с плавающей запятой в исходный код указана в C 2011 [черновик N1570]. 6.4.4.2. Это говорит о том, что рекомендуемая, но не обязательная практика заключается в том, что преобразование с плавающей запятой в конвертацию по времени должно соответствовать преобразованию последовательности символов в последовательности исполнения библиотечными функциями, такими как strtod
.
Более того, стандарт даже не требует, чтобы два разных литерала с одинаковым математическим значением, например 1.23
и 1.230
, конвертировались в одно и то же значение. Эти примеры взяты из сноски 75 в стандарте, которая является примечанием к абзацу, в котором говорится, что все константы с плавающей точкой одной и той же исходной формы преобразуются в одно и то же значение. Таким образом, 1.23
всегда преобразуется в одно и то же значение везде, где оно появляется в источнике, но 1.230
не обязательно преобразуется в то же значение, что и 1.23
или 123e-2
. Даже 123e-2
и 123e-02
могут быть разными.
atof(p)
указано в 7.22.1.2 эквивалентно strtod(p, (char **) NULL)
за исключением того, как они ведут себя с ошибками. strtod
указывается в 7.22.1.3. В этой статье есть некоторые рекомендуемые методы для точности, но они молчат о сопоставлении конверсии времени в литературе.
Ответ 2
Эта проверка неизбежно зависит от реализации, поэтому я написал следующий небольшой тестовый скрипт:
#include <stdio.h>
#include <stdlib.h>
int main()
{
double d1 = 1.2;
double d2 = atof("1.2");
char *p;
double d3 = strtod("1.2", &p);
printf("d1 = %40.40f\n", d1);
printf("d2 = %40.40f\n", d2);
printf("d3 = %40.40f\n", d3);
if(d1 != d2)
printf("d1 != d2\n");
if(d2 != d3)
printf("d2 != d3\n");
}
В случае компилятора HP C/C++, версия A.06.25.02, эти выходы
d1 = 1.1999999999999999555910790149937383800000
d2 = 1.1999999999999999555910790149937383800000
d3 = 1.1999999999999999555910790149937383800000
который показывает, что преобразование (равное 1,2, по меньшей мере), которое выполняется компилятором, соответствует преобразованиям, выполняемым atof
и strtod
.
Ответ 3
Из военной инженерии мы всегда учитываем эту проблему, установив диапазон допустимости + / - 0,000001 вокруг значения истинного значения поплавка. Таким образом, вы знаете, что вы действительно сравниваете и помогаете предотвратить загрязнение того, что разработан алгоритм. Один из них всегда работает с нечеткими числами при работе с числами с плавающей запятой, где нельзя или не следует выполнять жесткое сравнение.