浮点比较例程

来自RAD Studio
跳转到:航行,搜索

转到使用浮点例程

比较浮点数有几个不明显的问题。

浮点比较问题

一个浮点比较问题是,您看到的并不是数字在内存中的确切表示方式。你可以有X:=99.9999964Y“=100.000003数字,两者均显示为100,但不相等:

 使用
   系统.系统实用程序;
 无功功率,无功功率 X(X), Y(Y): 单个;
 开始
   X(X) := 99.9999964;
   Y(Y) := 100.000003;
   Writeln公司(“X=”, 浮点数到Str(X(X)));
   Writeln公司(“Y=”, 浮点数到Str(Y(Y)));   读取Ln;
 结束.

程序输出:

X=100Y=100

然而,如果你试图比较X和Y,它们并不相等。另一个相反的例子是:

 无功功率,无功功率 X(X):单个;
 开始
   X(X):=0.1;
   Writeln公司(“X=”, 浮点数到Str(X(X)));
 结束.

程序输出:

X=0.100000001490116

另一个问题源于浮点数的有限表示。让我们将浮点数与“自身”进行比较:

 无功功率,无功功率 X(X):单个;
 开始
  X(X):=0.1;
  如果 X(X)=0.1 然后
   Writeln公司(“相等”)
  其他的
   Writeln公司('不相等');
  读取Ln;
 结束.

程序输出:

不相等

为什么?要理解这一点,请记住,精确的十进制0.1数字具有二进制表示形式,即无限循环分数0.0(0011)。单个精度X只保留尾数的23位。Delphi使用以下命令执行所有浮点操作扩展精确度。当Delphi转换单个精度X到扩展具有63位尾数的表示,程序简单地用零初始化所有额外的位(而不是用0.0(0011)的实际位)。阅读有限精度含义了解更多信息。

现在让我们比较0.1英寸单个双精度精度:

 无功功率,无功功率
    X(X):单个;
    Y(Y):双精度;
 开始
  X(X):=0.1;
  Y(Y):=0.1;
  如果 X(X)=Y(Y) 然后
   Writeln公司(“相等”)
  其他的
   Writeln公司('不相等');
  读取Ln;
 结束.

程序输出:

不相等

阿盖恩单个双精度0.1表示保留不同的尾数位数。

比较例程

提供浮点数正确比较的解决方案是使用一些小的艾司隆保证金。如果两个浮点数的差值在艾司隆然后估计它们相等。

这个系统。数学单位提供比较值,SameValue公司、和IsZero(零)处理浮点比较的函数。这些函数具有如下声明:

 功能 比较值(常数 A类, B类: 扩展; 艾司隆: 扩展): T价值关系;
 功能 SameValue公司(常数 A类, B类: 扩展; 艾司隆: 扩展): 布尔值;
 功能 IsZero(零)(常数 A类: 扩展; 艾司隆: 扩展): 布尔值;

在这里A类B类是要比较的浮点数字和艾司隆是小边距A类B类可以不同,但仍被视为相同的值。

如果指定Epsilon=0然后隐式使用一些合理的默认值。例如扩展的版本SameValue公司使用默认值:

艾司隆 = 马克斯(分钟(防抱死制动系统(A类), 防抱死制动系统(B类)) * 1E-16级, 1E-16级)

另请参见