Я разрабатываю код, где мне приходится загружать значения с плавающей запятой, хранящиеся в каждой строке за раз в текстовом файле ... Я загрузил каждый из этих данных в массив поплавков, используя fscanf () ... однако я обнаружил, что плавающие точки были сохранены по-другому, пример 407.18 был сохранен как 407.179993, 414.35 как 414.350006 ... теперь я застреваю, потому что абсолютно важно, чтобы числа сохранялись в том виде, в каком они были в файле, но здесь это кажется другим, хотя, по сути, это то же самое .... как мне получить номера для хранения в оригинальной форме?Массив с плавающей точкой в C
ответ
Если абсолютно важно, чтобы номера сохранялись в форме, которую они были в файле, не используют значения с плавающей запятой. Не все дробные значения базы-10 могут быть представлены точно в двоичном формате.
Подробнее см. В статье "What Every Computer Scientist Should Know About Floating-Point Arithmetic" [PDF-ссылка].
Вы должны хранить номера в виде строки или в виде масштабированных целых чисел.
То, что вы видите, верно, поскольку плавающая точка не может точно представлять много действительных чисел. Это обязательное для чтения: What Every Computer Scientist Should Know About Floating-Point Arithmetic
Типы C++ float
и double
представлены в виде чисел с плавающей точкой IEEE. Существуют двоичные числа с плавающей запятой, а не десятичные числа. Они не имеют бесконечной точности, и даже относительно «простые» десятичные значения будут меняться при преобразовании в двоичную с плавающей запятой и обратно.
Языки, ориентированные на деньги (COBOL и PL/I, например), имеют десятичные типы данных, которые используют более медленные представления, которые не имеют этой проблемы. Для этой цели существуют библиотеки для C или C++, или вы можете использовать масштабированные целые числа, если вам не нужен слишком большой диапазон.
Возможно, вы захотите взглянуть на существующую библиотеку, которая реализует плавающие точки с контролируемым округлением. Я использовал MPFR. Это быстрый и открытый источник. Если вы работаете с деньгами, то другая библиотека будет лучше.
sfactor, Немного разъяснения: вы заявляете «... абсолютно важно, чтобы числа сохранялись в форме, в которой они были в файле» - что это за форма? Я принимаю форму отображения? Вот сделка: если вы храните файл 407.18, но отображается как 407.179993 - это абсолютно нормально и ожидается. Когда вы создаете свой sprintf или любой другой отформатированный шрифт, который вы используете, вы должны указать ему ограничение точности после десятичной точки. Это должно сделать трюк:
#include <stdio.h>
void main(void);
void main()
{
printf("%.2f",407.179993);
}
Существует множество способов хранения чисел - каждый со своими сильными и слабыми сторонами.
В вашем случае номера с плавающей точкой не являются лучшим выбором, потому что они не представляют собой самые действительные числа точно.
Масштабированные целые числа - это пример общей идиомы дизайна: отдельное представление из презентации.
Определите, сколько цифр вы хотите после десятичной точки, например. 2 цифры, как в 123,45. Затем вы должны внутренне представлять число как целое число 12345. Всякий раз, когда вы показываете значение для пользователя, вы должны вставить десятичную точку в соответствующее место.
Short InformIT article on Scaled Integers by Danny Kalev
Перед выходом за борт на масштабируемых целых сделать инспектировать домен вашей проблемы тесно утверждать, что «люфт» в числах с плавающей точкой является достаточно значительным, чтобы warrent с использованием масштабируемых целых чисел.
+1 для ссылки на статью; Я не знал, что есть версия HTML (и, извините, добавила ли я ссылку после того, как вы ответили, я редактировал свой ответ и не видел ваш, пока не опубликовал его). –