59 lines
1.6 KiB
ObjectPascal
59 lines
1.6 KiB
ObjectPascal
|
|
// in FPC 3.2.0 the definition of `integer` still depends on the compiler mode
|
|||
|
|
{$mode objFPC}
|
|||
|
|
|
|||
|
|
uses
|
|||
|
|
// used for `isInfinite`, `isNan` and `fMod`
|
|||
|
|
math,
|
|||
|
|
// NB: `ucomplex`’s `complex` isn’t a simple data type as ISO 10206 requires
|
|||
|
|
ucomplex;
|
|||
|
|
|
|||
|
|
{ --- determines whether a `float` value is (almost) an `integer` ------ }
|
|||
|
|
function isInteger(x: float; const fuzziness: float = 0.0): Boolean;
|
|||
|
|
// nested routine allows us to spare an `if … then` statement below
|
|||
|
|
function fuzzyInteger: Boolean;
|
|||
|
|
begin
|
|||
|
|
// `x mod 1.0` uses `fMod` function from `math` unit
|
|||
|
|
x := x mod 1.0;
|
|||
|
|
result := (x <= fuzziness) or (x >= 1.0 - fuzziness);
|
|||
|
|
end;
|
|||
|
|
begin
|
|||
|
|
{$push}
|
|||
|
|
// just for emphasis: use lazy evaluation strategy (currently default)
|
|||
|
|
{$boolEval off}
|
|||
|
|
result := not isInfinite(x) and not isNan(x) and fuzzyInteger;
|
|||
|
|
{$pop}
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{ --- check whether a `complex` number is (almost) in ℤ ---------------- }
|
|||
|
|
function isInteger(const x: complex; const fuzziness: float = 0.0): Boolean;
|
|||
|
|
begin
|
|||
|
|
// you could use `isZero` from the `math` unit for a fuzzy zero
|
|||
|
|
isInteger := (x.im = 0.0) and isInteger(x.re, fuzziness)
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{ --- test routine ----------------------------------------------------- }
|
|||
|
|
procedure test(const x: float);
|
|||
|
|
const
|
|||
|
|
tolerance = 0.00001;
|
|||
|
|
w = 42;
|
|||
|
|
var
|
|||
|
|
s: string;
|
|||
|
|
begin
|
|||
|
|
writeStr(s, 'isInteger(', x);
|
|||
|
|
writeLn(s:w, ') = ', isInteger(x):5,
|
|||
|
|
s:w, ', ', tolerance:7:5, ') = ', isInteger(x, tolerance):5);
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
{ === MAIN ============================================================= }
|
|||
|
|
begin
|
|||
|
|
test(25.000000);
|
|||
|
|
test(24.999999);
|
|||
|
|
test(25.000100);
|
|||
|
|
test(-2.1e120);
|
|||
|
|
test(-5e-2);
|
|||
|
|
test(NaN);
|
|||
|
|
test(Infinity);
|
|||
|
|
writeLn(isInteger(5.0 + 0.0 * i));
|
|||
|
|
writeLn(isInteger(5 - 5 * i));
|
|||
|
|
end.
|