Al *_*l C 10 delphi math floating-point comparison types
如果我有变量a,b,类型为double的c,设c:= a/b,并给出a和b值为7和10,则c的值为0.7,寄存器小于0.70.
另一方面,如果变量都是类型扩展的,则c的值0.7不会注册为小于0.70.
这看起来很奇怪.我错过了哪些信息?
Ken*_*ssa 18
首先,需要注意的是Delphi中的float文字属于Extended类型.因此,当您将double与文字进行比较时,double可能首先"扩展"为Extended,然后进行比较.(编辑:仅在32位应用程序中才是这样.在64位应用程序中,Extended是别名Double)
在这里,将显示所有ShowMessage.
procedure DoSomething;
var
A, B : Double;
begin
A := 7/10;
B := 0.7; //Here, we lower the precision of "0.7" to double
//Here, A is expanded to Extended... But it has already lost precision. This is (kind of) similar to doing Round(0.7) <> 0.7
if A <> 0.7 then
ShowMessage('Weird');
if A = B then //Here it would work correctly.
ShowMessage('Ok...');
//Still... the best way to go...
if SameValue(A, 0.7, 0.0001) then
ShowMessage('That will never fails you');
end;
Run Code Online (Sandbox Code Playgroud)
这里有一些文献给你
Pas*_*uoq 11
0.7二进制浮点数学数字没有表示.你的陈述计算在c最近的double,根据你的说法,我没有检查,是略低于0.7.
显然,在扩展精度中,最接近的浮点数为0.7,略高于它.但仍然没有确切的代表0.7.二进制浮点中没有任何精度.
根据经验,任何非最后一个非零小数不是5的非整数都不能完全表示为二进制浮点数(反之亦然:0.05也不能完全表示).
它与您正在使用的两种不同浮点类型中的精度位数有关,以及无论精度如何都无法准确表示大量数字的事实.(从纯粹的数学方面看:非理性数字超过有理数)
以2/3为例.它'不能用十进制表示.有4位有效数字,它表示为0.6667.有8位有效数字,当前为0.66666667.尾随7是综合反映,如果有空间保留它,下一个数字将> 5.
0.6667大于0.66666667,因此计算机将评估2/3(4位)> 2/3(8位).
双重和扩展变量中的.7 vs .70也是如此.
要避免此特定问题,请尝试在整个代码中使用相同的数字类型.一般使用浮点数时,有很多小事需要注意.最大的不是编写代码来比较两个浮点数是否相等 - 即使它们应该是相同的值,计算中有许多因素会使它们最终变得非常微小.您需要测试两个数字之间的差异是非常小的,而不是比较相等性.差异有多小取决于你和计算的性质,它通常被称为epsilon,取自微积分定理和证明.
你错过了这件事.
特别参见" 准确性问题 "一章.另见Pascal的答案.为了在不使用Extended类型的情况下修复代码,必须添加Math单元并使用SameValue专门为此目的而构建的功能.
Epsilon在您的情况下使用SameValue时,请务必使用不同于0 的值.
例如:
var
a, b, c: double;
begin
a:=7; b:=10;
c:=a/b;
if SameValue(c, 0.70, 0.001) then
ShowMessage('Ok')
else
ShowMessage('Wrong!');
end;
Run Code Online (Sandbox Code Playgroud)
HTH
| 归档时间: |
|
| 查看次数: |
3638 次 |
| 最近记录: |