3

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

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

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

-1.23456789012E-0002
-1.23456789034E-0002

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

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

4

6 回答 6

7

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

从德尔福帮助:

基本 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。

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

于 2008-09-29T19:28:05.093 回答
2

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

WriteLn(RealVar:12:3);

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

于 2008-09-29T21:01:40.467 回答
0

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

于 2008-09-29T19:11:51.293 回答
0

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

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

于 2008-09-29T19:34:00.850 回答
0

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

于 2008-10-01T08:28:14.273 回答
0

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

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

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

于 2008-10-16T04:41:06.697 回答