通过Delphi中的writeln / readln实现的实数精度

时间:2008-09-29 18:29:10

标签: delphi floating-point text-files precision

我的客户端应用程序使用writeln和readln通过文本文件导出和导入很多类型为real的变量。我试图增加所写字段的宽度,以便代码看起来像:

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

当我导出然后再次导入和导出并比较文件时,我得到了最后两位数的差异,例如(可能在这里的实际位数上有所不同但是你得到了它):

-1.23456789012E-0002
-1.23456789034E-0002

这实际上对应用程序产生了影响,因此客户想知道我能做些什么。现在我不确定它只是写/读这样做但是我想在我再次潜入嘿堆栈之前我会抛出一个快速的问题。我需要对此进行二元化吗?

这不是处理货币或其他东西的应用程序,我只是在文件中写入和读取值。我知道浮点有时候有点奇怪,我认为其中一个例程(writeln / readln)可能会有一些有趣的事情发生。

6 个答案:

答案 0 :(得分:7)

您可以尝试切换到扩展以获得更高的精确度。正如所指出的那样,浮点数只有很多有效精度数字,因此仍然可以显示更多数字然后准确存储,这可能会导致您指定的行为。

来自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   
  

注意:在早期版本的Object Pascal中,六字节 Real48 类型被称为 Real 。如果要重新编译在Delphi中使用较旧的六字节Real类型的代码,您可能需要将其更改为 Real48 。您还可以使用{$ REALCOMPATIBILITY ON}编译器指令将 Real 恢复为六字节类型。以下评论适用于基本实物类型。

     
      
  • Real48 是为了向后兼容而维护的。由于其存储格式不是英特尔处理器架构的原生格式,因此导致性能低于其他浮点类型。
  •   
  • 扩展提供比其他真实类型更高的精度,但便携性较差。如果要创建要跨平台共享的数据文件,请小心使用Extended。
  •   

请注意,范围大于有效数字。所以你可以有一个更大的数字然后可以准确存储。我建议四舍五入到有效数字以防止这种情况发生。

答案 1 :(得分:2)

如果要使用WriteLn指定实数的精度,请使用以下命令:

WriteLn(RealVar:12:3);

它输出Realvar值至少12个位置,精度为3。

答案 2 :(得分:0)

使用浮点类型时,您应该了解指定类型的精度限制。例如,4字节IEEE-754类型只有大约7.5个有效数字的精度。八字节IEEE-754类型的有效位数大约是其两倍。显然,delphi实数类型的精度大约为11位有效数字。结果是,您指定的格式的任何额外数字可能是噪声,可能导致基数10格式值和基数2浮点值之间的转换。

答案 3 :(得分:0)

首先,我会尝试查看是否可以通过使用不同参数的Str或者提高应用中类型的精度来获得任何帮助。 (你尝试过使用Extended吗?)

作为最后的手段,(警告!解决方法!! )我会尝试将客户的字符串表示与二进制表示一起保存在排序列表中。在写回浮点值之前,我会看到表中是否已存在匹配值,其字符串表示形式已知且可以替代使用。为了快速获得此查找,您可以对数值进行排序,并使用二进制搜索来找到最佳匹配。

答案 4 :(得分:0)

根据您需要处理的处理量,替代方法可以是将数字保持为BCD格式以保持原始准确度。

答案 5 :(得分:0)

如果不知道您的ExportRealValue和ImportRealValue是什么类型,很难回答这个问题。正如其他人所提到的,真实类型都有不同的精确度。

值得注意的是,与某种想法相反,延伸并不总是更高的精度。扩展是10-20个重要数字,其中双倍是15-16。当你在第十个sig fig附近遇到麻烦时,也许你已经使用了扩展。

要获得对读取和写入的更多控制,您可以自己将数字转换为字符串,并将其写入文件流。至少就是这样,你不必担心如果读取和写入背后都没有好处。