【问题标题】:Precision of reals through writeln/readln in DelphiDelphi 中通过 writeln/readln 的实数精度
【发布时间】:2010-09-14 01:57:44
【问题描述】:

我的客户应用程序使用 writeln 和 readln 通过文本文件导出和导入大量 real 类型的变量。我试图增加所写字段的宽度,因此代码如下所示:

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

当我导出然后再次导入和导出并比较文件时,我得到最后两位数字的差异,例如(这里的实际位数可能不正确,但你明白了):

-1.23456789012E-0002
-1.23456789034E-0002

这实际上对应用程序产生了影响,因此客户想知道我能做些什么。现在我不确定是否只有写入/读取才能做到这一点,但我想在我再次深入讨论堆栈之前我会提出一个快速的问题。我需要对此进行二进制处理吗?

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

【问题讨论】:

标签: delphi floating-point text-files precision


【解决方案1】:

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

值得注意的是,与某些想法相反,扩展并不总是更高的精度。扩展是 10-20 有效数字,其中双倍是 15-16。由于您在第十个 sig fig 附近遇到问题,也许您已经在使用 extended。

为了更好地控制读取和写入,您可以自己将数字转换为字符串,然后将它们写入文件流。至少这样你就不用担心 readln 和 writeln 在你背后做坏事了。

【讨论】:

    【解决方案2】:

    根据您需要进行多少处理,另一种方法是将数字保留为 BCD 格式以保持原始准确性。

    【讨论】:

      【解决方案3】:

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

      WriteLn(RealVar:12:3);
      

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

      【讨论】:

        【解决方案4】:

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

        来自 Delphi 帮助:

        基本的 Win32 实数类型

        |意义重大 |尺寸 类型 |范围 |数字 |字节 ------+----------------------+------ --------+---------- 真实 | -5.0 x 10^–324 .. 1.7 x 10^308 | 15-16 | 8 真实48 | -2.9 x 10^–39 .. 1.7 x 10^38 | 11-12 | 6 单身 | -1.5 x 10^–45 .. 3.4 x 10^38 | 7-8 | 4 双 | -5.0 x 10^–324 .. 1.7 x 10^308 | 15-16 | 8 扩展 | -3.6 x 10^–4951 .. 1.1 x 10^4932 | 10-20 | 10 比较 | -2^63+1 .. 2^63–1 | 10-20 | 8 货币 | -922337203685477.5808.. | | 922337203685477.5807 | 10-20 | 8

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

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

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

        【讨论】:

          【解决方案5】:

          首先,我会尝试看看是否可以通过使用带有不同参数的 Str 或提高应用程序中类型的精度来获得任何帮助。 (您是否尝试过使用扩展?)

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

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              猜你喜欢
              • 2022-01-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-07-27
              • 1970-01-01
              • 1970-01-01
              • 2017-06-10
              • 2016-04-18
              相关资源
              最近更新 更多