71 lines
1.6 KiB
ObjectPascal
71 lines
1.6 KiB
ObjectPascal
program approximateEqual(output);
|
|
|
|
{
|
|
\brief determines whether two `real` values are approximately equal
|
|
\param x a reference value
|
|
\param y the value to compare with \param x
|
|
\return true if \param x is equal or approximately equal to \param y
|
|
}
|
|
function equal(protected x, y: real): Boolean;
|
|
function approximate: Boolean;
|
|
function d(protected x: real): integer;
|
|
begin
|
|
d := trunc(ln(abs(x) + minReal) / ln(2)) + 1
|
|
end;
|
|
begin
|
|
approximate := abs(x - y) <= epsReal * (maxReal / (d(x) + d(y)))
|
|
end;
|
|
begin
|
|
equal := (x = y) or_else (x * y >= 0.0) and_then approximate
|
|
end;
|
|
|
|
{ --- auxilliary routines ---------------------------------------------- }
|
|
procedure test(protected x, y: real);
|
|
const
|
|
{ ANSI escape code for color coding }
|
|
CSI = chr(8#33) + '[';
|
|
totalMinimumWidth = 40;
|
|
postRadixDigits = 24;
|
|
begin
|
|
write(x:totalMinimumWidth:postRadixDigits, '':1, CSI, '1;3');
|
|
|
|
if equal(x, y) then
|
|
begin
|
|
if x = y then
|
|
begin
|
|
write('2m≅')
|
|
end
|
|
else
|
|
begin
|
|
write('5m≆')
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
write('1m≇')
|
|
end;
|
|
|
|
writeLn(CSI, 'm', '':1, y:totalMinimumWidth:postRadixDigits)
|
|
end;
|
|
|
|
{ === MAIN ============================================================= }
|
|
var
|
|
n: integer;
|
|
x: real;
|
|
begin
|
|
{ Variables were used to thwart compile-time evaluation done }
|
|
{ by /some/ compilers potentially confounding the results. }
|
|
n := 2;
|
|
x := 100000000000000.01;
|
|
|
|
test(x, 100000000000000.011);
|
|
test(100.01, 100.011);
|
|
test(x / 10000.0, 1000000000.0000001000);
|
|
test(0.001, 0.0010000001);
|
|
test(0.000000000000000000000101, 0.0);
|
|
x := sqrt(n);
|
|
test(sqr(x), 2.0);
|
|
test((-x) * x, -2.0);
|
|
test(3.14159265358979323846, 3.14159265358979324)
|
|
end.
|