Проблема преобразования в ANSI C

Возможные дубликаты:
Примеры неточности с плавающей запятой
Не работает ли математика JavaScript?

Мне нужно преобразовать некоторые данные из txt файла в двойное значение, и я использую для этого эту функцию: atof. Проблема в том, что значение, которое необходимо преобразовать, равно 5.550000, а функция atof возвращает 5.5499999999999998, и это проблема, потому что я должен вычислить средний балл с этим числом, а результат не является точным. Это функция, которая читает данные из txt файла:

void readNext(FILE* file,Lab* lab)
{
    char line[100];
getline(file,line,100);
if (strcmp(line,"") == 0)
{
    lab->is_null = 1;
    return;
}
strcpy(lab->date,line);
getline(file,line,100);
lab->presence = atoi(line);
getline(file,line,100);
strcpy(lab->num_work,line);
getline(file,line,100);
lab->mark_work = atof(line);
getline(file,line,100);
lab->test_work = atof(line);
getline(file,line,100);
lab->current = atof(line);
getline(file,line,100);
lab->status_work = atoi(line);
getline(file,line,100);
}

person Jordan Borisov    schedule 31.05.2011    source источник


Ответы (3)


drhirsch верен - 5.55 не может быть точно представлен в двоичной системе с плавающей запятой ( точно так же, как 1 ÷ 7 не может быть точно представлен в десятичном виде).

Однако для ваших целей это не должно быть проблемой, потому что число с плавающей запятой определенно может хранить 5,55 с точностью до трех разрядов, то есть число, которое у вас есть. Это просто означает, что вам нужно использовать правильный формат при печати - в данном случае %.3g. Когда вы рассчитываете средний балл, ваши расчеты по-прежнему будут точными до трех раз, потому что расчет среднего не вызывает катастрофической отмены.

person caf    schedule 01.06.2011

См. эту статью на StackOverflow.

У поплавков будут проблемы с отображением точных значений без дополнительной работы. Вы столкнетесь с двумя проблемами (описанными в связанной публикации) - фактическим округлением и форматированием.

person DaveE    schedule 31.05.2011

Краткий ответ: atof("5.55") никогда не вернет точное (то есть точное) представление этой десятичной дроби, потому что не существует точного двоичного представления этого числа с плавающей запятой, это бесконечная двоичная дробь.

Подробный ответ см. На странице http://www.math.umd.edu/~jkolesar/mait613/floating_point_math.pdf.

person Gunther Piez    schedule 31.05.2011