代码之家  ›  专栏  ›  技术社区  ›  dummzeuch Stijn Sanders

Delphi/Borland-Pascal STR程序是如何循环的

  •  4
  • dummzeuch Stijn Sanders  · 技术社区  · 16 年前

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

    如果舍入不含糊,则一切正常,但如果舍入不含糊(0.5->向上还是向下?)有一个问题:它似乎取决于BP中的浮点数据类型,但在Delphi 2007中显然是一致的:

    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' }
    

    我找不到任何关于双打如何取整的规则,而显然延长的总是取整的。

    有人知道双值的四舍五入是如何在BP中进行的吗?

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

    5 回复  |  直到 15 年前
        1
  •  4
  •   kludg    16 年前

    2.15不能用浮点格式精确表示,因此如果不分析给定浮点格式中浮点值的二进制表示形式,就不可能说出该值是如何舍入的;

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

    我测试了一些用浮点格式精确表示的值的舍入,发现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' }
    
        2
  •  2
  •   Jeff Wilhite    16 年前

    我认为你看到的问题是,许多可以用十进制表示法精确表示的数字只能用二进制的重复小数来表示。因此,可能2.15不能用双精度表示,而2.149999999234(或其他)是用二进制表示法可以得到的最接近的值。

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

        3
  •  1
  •   Mason Wheeler    16 年前

    看起来像是浮点舍入错误。当您查看在Delphi中生成的汇编代码时,您可以看到这两个操作都调用了\u Str2Ext,它将扩展名转换为字符串。因此,为了做到这一点,它必须把你的替身变成一个延伸的幕后:

    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 
    

        4
  •  0
  •   Mark Robinson    16 年前

    我对此进行了研究,发现添加0.000001将产生正确的双倍结果。

        5
  •  0
  •   Marco van de Voort    16 年前

    注意这里有两个方面。

    首先,十进制文字值可能被舍入为二进制浮点数。这意味着,放入汇编代码中的数字可能与您写下的数字略有不同。如果最近的machinenumber稍微小一些,它可能会显示为应该向上舍入的值被STR向下舍入。

    第二,使用FPU statusword中配置的舍入,对得到的二进制浮点数进行舍入,希望外部库不会更改这个舍入。