如何在delphi中比较double?

时间:2011-05-24 05:35:58

标签: delphi types

我们面临数据类型双重比较的问题:

if(p > pmax) then
begin
  Showmessage('');
end

如果两个值均为100(p = 100且pmax = 100),那么它也会进入if子句。

2 个答案:

答案 0 :(得分:58)

Math.pas单元包含SameValue()IsZero()CompareValue()等函数,用于处理浮动类型比较和相等。

const
  EPSILON = 0.0000001;
begin    
  if CompareValue(p, pMax, EPSILON) = GreaterThanValue then
    ShowMessage('p greater than pMax');

常量GreaterThanValue在Types.pas

中定义

如果您要比较非常大的值,则不应使用epsilon的常量,而应根据您要比较的值计算您的epsilon值。

var
  epsilon: double;
begin    
  epsilon := Max(Min(Abs(p), Abs(pMax)) * 0.000001, 0.000001);
  if CompareValue(p, pMax, epsilon) = GreaterThanValue then
    ShowMessage('p greater than pMax');

请注意,如果您使用CompareValue(a, b, 0)或在XE2及更高版本CompareValue(a, b)中使用,Delphi将自动为您填写好的epsilon。

来自Delphi Math单元:

function SameValue(const A, B: Extended; Epsilon: Extended): Boolean;
begin
  if Epsilon = 0 then
    Epsilon := Max(Min(Abs(A), Abs(B)) * ExtendedResolution, ExtendedResolution);
  if A > B then
    Result := (A - B) <= Epsilon
  else
    Result := (B - A) <= Epsilon;
end;

从Delphi XE2开始,现在所有这些函数都有重载,不需要epsilon参数,而是为你计算一个(类似于为epsilon传递0值)。为了代码清晰,我建议调用这些更简单的函数,让Delphi处理epsilon。

没有epsilon参数时不使用重载的唯一原因是当性能至关重要并且你想避免重复计算epsilon的开销时。

答案 1 :(得分:12)

比较双打有几个问题。一个问题是你所看到的并不完全是因为四舍五入而得到的。你可以有99.999999996423和100.00000000001632,它们都是四舍五入到100,但它们不相等。

解决方案是使用保证金,这样,如果两个双打的差异在保证金范围内,则接受它们是相等的。

您可以使用边距作为可选参数创建IsEqual函数:

function IsEqual(const ANumber1, ANumber2: Double; const AMargin: Double = cMargin): Boolean;
begin
  Result := Abs(ANumber1-ANumber2) <= AMargin;
end;