2009-12-05 4 views
1

Я разрабатываю код, где мне приходится загружать значения с плавающей запятой, хранящиеся в каждой строке за раз в текстовом файле ... Я загрузил каждый из этих данных в массив поплавков, используя fscanf () ... однако я обнаружил, что плавающие точки были сохранены по-другому, пример 407.18 был сохранен как 407.179993, 414.35 как 414.350006 ... теперь я застреваю, потому что абсолютно важно, чтобы числа сохранялись в том виде, в каком они были в файле, но здесь это кажется другим, хотя, по сути, это то же самое .... как мне получить номера для хранения в оригинальной форме?Массив с плавающей точкой в ​​C

ответ

17

Если абсолютно важно, чтобы номера сохранялись в форме, которую они были в файле, не используют значения с плавающей запятой. Не все дробные значения базы-10 могут быть представлены точно в двоичном формате.

Подробнее см. В статье "What Every Computer Scientist Should Know About Floating-Point Arithmetic" [PDF-ссылка].

Вы должны хранить номера в виде строки или в виде масштабированных целых чисел.

11

То, что вы видите, верно, поскольку плавающая точка не может точно представлять много действительных чисел. Это обязательное для чтения: What Every Computer Scientist Should Know About Floating-Point Arithmetic

+0

+1 для ссылки на статью; Я не знал, что есть версия HTML (и, извините, добавила ли я ссылку после того, как вы ответили, я редактировал свой ответ и не видел ваш, пока не опубликовал его). –

2

Типы C++ float и double представлены в виде чисел с плавающей точкой IEEE. Существуют двоичные числа с плавающей запятой, а не десятичные числа. Они не имеют бесконечной точности, и даже относительно «простые» десятичные значения будут меняться при преобразовании в двоичную с плавающей запятой и обратно.

Языки, ориентированные на деньги (COBOL и PL/I, например), имеют десятичные типы данных, которые используют более медленные представления, которые не имеют этой проблемы. Для этой цели существуют библиотеки для C или C++, или вы можете использовать масштабированные целые числа, если вам не нужен слишком большой диапазон.

0

Возможно, вы захотите взглянуть на существующую библиотеку, которая реализует плавающие точки с контролируемым округлением. Я использовал MPFR. Это быстрый и открытый источник. Если вы работаете с деньгами, то другая библиотека будет лучше.

2

sfactor, Немного разъяснения: вы заявляете «... абсолютно важно, чтобы числа сохранялись в форме, в которой они были в файле» - что это за форма? Я принимаю форму отображения? Вот сделка: если вы храните файл 407.18, но отображается как 407.179993 - это абсолютно нормально и ожидается. Когда вы создаете свой sprintf или любой другой отформатированный шрифт, который вы используете, вы должны указать ему ограничение точности после десятичной точки. Это должно сделать трюк:

#include <stdio.h> 
void main(void); 
void main() 
{ 
    printf("%.2f",407.179993); 
} 
0

Существует множество способов хранения чисел - каждый со своими сильными и слабыми сторонами.

В вашем случае номера с плавающей точкой не являются лучшим выбором, потому что они не представляют собой самые действительные числа точно.

Масштабированные целые числа - это пример общей идиомы дизайна: отдельное представление из презентации.

Определите, сколько цифр вы хотите после десятичной точки, например. 2 цифры, как в 123,45. Затем вы должны внутренне представлять число как целое число 12345. Всякий раз, когда вы показываете значение для пользователя, вы должны вставить десятичную точку в соответствующее место.

Short InformIT article on Scaled Integers by Danny Kalev

Перед выходом за борт на масштабируемых целых сделать инспектировать домен вашей проблемы тесно утверждать, что «люфт» в числах с плавающей точкой является достаточно значительным, чтобы warrent с использованием масштабируемых целых чисел.