【问题标题】:Delphi check if double is an integer or notDelphi 检查 double 是否为整数
【发布时间】:2021-11-05 05:23:10
【问题描述】:

我需要测试一个双精度数是否为整数。基本上这是规则的一个例子:

  • 5.0 > 真
  • 5.2 > 错误

为了做到这一点,我会创建一个if (result mod 1) = 0 then 并查看它是否返回真或假。考虑result 是双精度。顺便说一句,编译器给了我这个错误:

[dcc32 Error] Unit1.pas(121): E2015 Operator not applicable to this 操作数类型

我该如何解决这个问题?请注意,我的数字采用这种格式##.#####,所以我在浮点精度方面没有太多问题。

一般我会使用if (result % 1 == 0) {},但在 Delphi 中这不起作用。

【问题讨论】:

  • 您可以检查分数是否接近于零。 “math”有“IsZero”,您可以提供一个 epsilon。
  • 一个精确的整数,还是足够接近?如果只是一个精确的整数,请记住像0.2 + 0.2 + 0.2 + 0.2 + 0.2 这样的简单事物不一定会计算为精确的整数。如果足够近,多近?
  • @SertacAkyuz 你可以这样做,但是将 1 变为 1.0000001 的舍入误差百分比将 1000000 变为 1000000.1。只看小数部分而不考虑大小可能不是一个好主意。
  • @hvd - 如果差异太大,您可以根据大小提供不同的 epsilon。
  • 检查这个简单的解决方案,希望对某人有所帮助:stackoverflow.com/a/62449962/8545027

标签: delphi


【解决方案1】:

您可以使用在Delphi 的System 单元中声明的函数frac。试试这段代码:

if ( frac(result) = 0 ) then
 ShowMessage('is zero')
else
 ShowMessage('is NOT zero');
end;

查看documentation 了解有关该功能的详细信息。您所做的事情是错误的,因为在 Delphi 中,关键字 mod 仅适用于整数。


注意。我已经用45.1234 之类的数字对此进行了测试,并且代码是正确的。我看到你的双精度数很少,所以应该没有问题。我不确定这个函数有多准确,但在这种情况下你不必担心。

【讨论】:

  • 小心使用Frac(),因为Delphi 确实有一些浮动问题。给定一个值为 15.2 的变量 V: DoubleFrac(V) 返回 0.199999999999999。这是使用 Delphi 10.2
【解决方案2】:

这种比较适用于 Freepascal....

{$mode objfpc}{$R+}
uses math;
var
  a:double =  5.2;
  b:double =  5.0;
begin
  writeln(a mod 1 = 0);
writeln(b mod 1 = 0);
end.

但它不会在 Delphi 中工作,我知道...

在 Delphi 中应该使用 fmod:

uses math;
var
  a:double =  5.2;
  b:double =  5.0;
begin
  writeln(fmod(a,1) = 0);
  writeln(fmod(b,1) = 0);
end.

【讨论】:

    【解决方案3】:

    @Alberto 答案的变体。稍微改进一下,让人们可以选择你想要的精确度(或不精确度):

    // is the passed FP number effectively an "integer";
    // i.e. when rounded to AToPlaces decimal places, does it have only zero after dec point?
    // AToPlaces -ve => after the dec point; same convention as for RoundTo; range -20 .. +20
      
    function IsInteger(AFloat: Extended; AToPlaces: TRoundToEXRangeExtended = -3): boolean;
    begin
      // Careful, this didn't work until I switched the order of Frac and RoundTo
      result := RoundTo(frac(AFloat), AToPlaces) = 0;
    end;
    

    【讨论】:

      【解决方案4】:

      也许你还想注意浮点不精确,这样你就可以做这样的事情:

      if comparevalue(aValue, round(aValue), Tepsilon.vector) = 0 then 
        hasnodecimal 
      else 
        hasdecimal
      

      【讨论】:

      • 如果您检查comparevalue 的源代码,您可以将代码简化为Abs(aValue - Round(aValue)) < Tepsilon.vector,然后几乎可以简化为frac(aValue) < Tepsilon.vector 的Alberto Miola 答案。
      猜你喜欢
      • 2023-03-20
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      • 2011-05-03
      • 2016-05-19
      • 1970-01-01
      相关资源
      最近更新 更多