3
votes

I need to test if a double is an integer or not. Basically this is an example of the rule:

  • 5.0 > true
  • 5.2 > false

In order to do this I'd make an if (result mod 1) = 0 then and see the if it returns true or false. Consider that result is a double. By the way the compiler gives me this error:

[dcc32 Error] Unit1.pas(121): E2015 Operator not applicable to this operand type

How can I solve this problem? Note that my numbers are in this format ##.##### so I haven't many problems with the floating point precision.

In general I'd use if (result % 1 == 0) {} but in Delphi this does not work.

3
You can check if the fraction is close to zero. "math" has "IsZero" which you can provide an epsilon. - Sertac Akyuz
An exact integer, or close enough? If only an exact integer, keep in mind that simple things such as 0.2 + 0.2 + 0.2 + 0.2 + 0.2 don't necessarily evaluate to an exact integer. If close enough, how close? - user743382
@SertacAkyuz You could do that, but the same percentages in rounding errors that turn 1 into 1.0000001 turn 1000000 into 1000000.1. Only looking at the fractional part without taking the magnitude into account is probably not a good idea. - user743382
@hvd - You can provide different epsilons according to magnitude if it is differing too much. - Sertac Akyuz
Check this simple solution, hope it help someone : stackoverflow.com/a/62449962/8545027 - Mostafa Amer

3 Answers

9
votes

You can use the function frac declared in the System unit of Delphi. Try with this code:

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

Check the documentation for details about the function. What you are doing is wrong because in Delphi the keyword mod only works with Integers.


Note. I have tested this with numbers such as 45.1234 and the code is correct. I see that you have a little number of digits in your double so there shouldn't be problems. I am not sure how accurate that function is, but in this case you don't have to worry.

0
votes

That comparison would work in 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.

But it won't work in Delphi, I know...

In Delphi it should be with fmod:

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

maybe you want also to take care about the float imprecision, in this way you can do something like this :

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