Преобразует строку в двойную, равную буквальному двойнику?

Например:

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 вокруг значения истинного значения поплавка. Таким образом, вы знаете, что вы действительно сравниваете и помогаете предотвратить загрязнение того, что разработан алгоритм. Один из них всегда работает с нечеткими числами при работе с числами с плавающей запятой, где нельзя или не следует выполнять жесткое сравнение.