首页 文章

Delphi / Borland Pascal STR程序是如何进行的

提问于
浏览
4

Borland Pascal 7和Delphi 2007都得到了一个STR程序STR,它取一个数字,一个长度和精度,并将它转换为如下字符串:

str(9.234:5:1, s); // -> s = '  9.2'

如果舍入是非模糊的,那么一切都很好,但如果它不是(0.5 - >向上或向下吗?)则存在一个问题:它似乎依赖于BP中的浮点数据类型,但在Delphi 2007中显然是一致的:

BP:

var
  e: extended;
  d: double;
begin
  d := 2.15;
  e := 2.15;
  str(d:5:1, s); { -> s = '  2.1' }
  str(e:5:1, s); { -> s = '  2.2' }
  { but: }
  d := 2.25
  e := 2.25
  str(d:5:1, s); { -> s = '  2.3' }
  str(e:5:1, s); { -> s = '  2.3' }

我无法找到关于双打如何被舍入的任何规则,而显然扩展总是四舍五入 .

Delphi 2007显然总是独立于数据类型 .

有人知道如何在BP中进行舍入以获得双值吗?

我想知道,因为我正在移植一些使用双精度到Delphi 2007的Borland Pascal代码,当我比较输出时,我得到了STR程序中的舍入导致的不一致 . 这些对结果并不重要,但却很难发现重要的差异 .

5 回答

  • 2

    我认为你看到的问题是,许多可以用十进制表示法精确表示的数字只能用二进制表示为重复小数(二进制?) . 因此,可能2.15不能用double精确表示,2.14999999999234(或其他)是二进制表示最接近的 .

    由于数字的最接近二进制表示严格小于2.15,因此Str函数向下舍入而不是向上舍入 .

  • 0

    d = 2.15和d = 2.25的情况不同:

    2.15不能以float格式精确表示,因此如果不分析给定float格式的float值的二进制表示,就不可能说明该值是如何舍入的;

    2.25以float格式精确表示,舍入结果必须是可预测的;

    我测试了一些以浮点格式精确表示的值的舍入,发现STR总是向上舍入为正值,向下舍入为负值 . STR不遵循“银行家的舍入”,例如:

    d := 2.25;
    //  d:= roundto(d, -1);  banker's rounding is 2.2
      str(d:5:1, s); { -> s = '  2.3' }
    
      d:= 2.75;
    //  d:= roundto(d, -1);  banker's rounding is 2.8
      str(d:5:1, s); { -> s = '  2.8' }
    
  • 4

    看起来像浮点舍入错误 . 当您查看在Delphi中生成的汇编代码时,您可以看到为两个操作调用了_Str2Ext,它将Extended转换为字符串 . 所以为了做到这一点,它必须将你的Double转换为幕后扩展:

    Project1.dpr.16: str(d:5:1, s); { -> s = '  2.1' }
    0040E666 DD45E8           fld qword ptr [ebp-$18]
    0040E669 83C4F4           add esp,-$0c
    0040E66C DB3C24           fstp tbyte ptr [esp]
    0040E66F 9B               wait
    

    在从Double到Extended的转换中,你会失去一点精确度,并且最终会有一个稍微不同的数字,而不是你声明相同的数字(我们读它们)作为扩展开始 . 这在浮点转换中非常常见 . 不确定你能做些什么吗?

  • 1

    我调查了这一点,发现添加0.000001会产生双打的正确结果 .

  • 0

    请注意,这里有两个方面 .

    首先,您的十进制文字值可能舍入为二进制浮点数 . 这意味着汇编代码中的数字可能与您记下的数字略有不同 . 如果最近的机器编号略小,则可能看起来好像应该向上舍入的值向下舍入STR .

    其次,使用FPU状态字中配置的舍入对生成的二进制浮点数进行舍入,希望外部库未对其进行更改 .

相关问题