Вопрос

Мое клиентское приложение экспортирует и импортирует довольно много переменных типа real через текстовый файл, используя writeln и readln.Я попытался увеличить ширину написанных полей, чтобы код выглядел следующим образом:

writeln(file, exportRealvalue:30); //using excess width of field
....
readln(file, importRealvalue);

Когда я экспортирую, а затем импортирую и экспортирую снова и сравниваю файлы, я получаю разницу в последних двух цифрах, например (здесь может быть указано фактическое количество цифр, но вы его понимаете):

-1.23456789012E-0002
-1.23456789034E-0002

Это действительно меняет ситуацию в приложении, поэтому клиент хочет знать, что я могу с этим поделать.Теперь я не уверен, что это делает только запись / чтение, но я подумал, что задам короткий вопрос, прежде чем снова погрузиться в стек hey.Нужно ли мне для этого использовать двоичный код?

Это не приложение, имеющее дело с валютой или чем-то еще, я просто записываю и считываю значения в / из файла.Я знаю, что плавающие точки иногда немного странные, и я подумал, что в одной из подпрограмм (writeln / readln) может происходить что-то забавное.

Это было полезно?

Решение

Если вы хотите указать точность реального значения с помощью WriteLn, используйте следующее:

WriteLn(RealVar:12:3);

Он выводит значение Realvar как минимум с 12 позициями и точностью 3.

Другие советы

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

Из справки Delphi:

Основные реальные типы Win32

                                            | Significant | Size in 
Type     | Range                            | digits      | bytes
---------+----------------------------------+-------------+----------
Real     | -5.0 x 10^–324 .. 1.7 x 10^308   | 15–16       |   8  
Real48   | -2.9 x 10^–39 .. 1.7 x 10^38     | 11-12       |   6   
Single   | -1.5 x 10^–45 .. 3.4 x 10^38     |  7-8        |   4   
Double   | -5.0 x 10^–324 .. 1.7 x 10^308   | 15-16       |   8   
Extended | -3.6 x 10^–4951 .. 1.1 x 10^4932 | 10-20       |  10   
Comp     | -2^63+1 .. 2^63–1                | 10-20       |   8   
Currency | -922337203685477.5808..          |             | 
                    922337203685477.5807    | 10-20       |   8   

Примечание:Шестибайтовый Реальный 48 тип был назван Реальный в более ранних версиях Object Pascal.Если вы перекомпилируете код, использующий более старый шестибайтовый реальный тип в Delphi, вы можете захотеть изменить его на Реальный 48.Вы также можете использовать директиву компилятора {$REALCOMPATIBILITY ON}, чтобы включить Реальный вернемся к шестибайтовому типу.Следующие замечания применимы к фундаментальным реальным типам.

  • Реальный 48 поддерживается для обеспечения обратной совместимости.Поскольку его формат хранения не является родным для архитектуры процессора Intel, это приводит к снижению производительности по сравнению с другими типами с плавающей запятой.
  • Расширенный обеспечивает большую точность, чем другие реальные типы, но менее портативен.Будьте осторожны при использовании Extended, если вы создаете файлы данных для совместного использования на разных платформах.

Обратите внимание, что диапазон больше значащих цифр.Таким образом, у вас может быть число больше, чем может быть точно сохранено.Я бы рекомендовал округлять до значащих цифр, чтобы этого не произошло.

При использовании типов с плавающей запятой вы должны знать об ограничениях точности для указанных типов.Например, 4-байтовый тип IEEE-754 имеет точность всего около 7,5 значащих цифр.Восьмибайтовый тип IEEE-754 содержит примерно вдвое больше значащих цифр.По-видимому, реальный тип delphi имеет точность, которая составляет около 11 значащих цифр.Результатом этого является то, что любые дополнительные цифры форматирования, которые вы указываете, вероятно, будут шумом, который может привести к преобразованиям между базовыми значениями в формате 10 и базовыми значениями с плавающей запятой 2.

Прежде всего, я бы попытался посмотреть, смогу ли я получить какую-либо помощь от использования Str с различными аргументами или повышения точности типов в вашем приложении.(Вы пробовали использовать Extended?)

В качестве последнего средства, (Внимание!Обходной путь!!) Я бы попробовал сохранить строковое представление клиента вместе с двоичным представлением в отсортированном списке.Прежде чем записывать обратно значение с плавающей запятой, я бы посмотрел, есть ли уже соответствующее значение в таблице, строковое представление которого уже известно и может быть использовано вместо него.Чтобы ускорить этот поиск, вы можете отсортировать его по числовому значению и использовать двоичный поиск для поиска наилучшего соответствия.

В зависимости от того, какой объем обработки вам необходимо выполнить, альтернативой может быть сохранение чисел в формате BCD для сохранения первоначальной точности.

Трудно ответить на этот вопрос, не зная, к какому типу относятся ваши ExportRealValue и ImportRealValue.Как уже упоминали другие, все реальные типы имеют разную точность.

Стоит отметить, вопреки некоторым представлениям, расширенная точность не всегда выше.Расширенный - это 10-20 значащих цифр, где двойной - 15-16.Поскольку у вас возникли проблемы с десятым сигналом, возможно, вы уже используете extended.

Чтобы получить больший контроль над чтением и записью, вы можете самостоятельно преобразовывать числа в строки и обратно и записывать их в файловый поток.По крайней мере, так вам не придется беспокоиться, что readln и writeln замышляют что-то недоброе за вашей спиной.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top