Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,2 @@
---
from: http://rosettacode.org/wiki/Approximate_equality

View file

@ -0,0 +1,32 @@
Sometimes, when testing whether the solution to a task (for example, here on Rosetta Code) is correct, the
difference in floating point calculations between different language implementations becomes significant.
For example, a difference between '''32''' bit and '''64''' bit floating point calculations may appear by
about the 8th significant digit in base 10 arithmetic.
;Task:
Create a function which returns true if two floating point numbers are approximately equal.
The function should allow for differences in the magnitude of numbers, so that, for example,
<br>'''100000000000000.01''' &nbsp; may be approximately equal to &nbsp; '''100000000000000.011''',
<br>even though &nbsp; '''100.01''' &nbsp; is not approximately equal to &nbsp; '''100.011'''.
If the language has such a feature in its standard library, this may be used instead of a custom function.
Show the function results with comparisons on the following pairs of values:
:# &nbsp; &nbsp; 100000000000000.01, &nbsp; 100000000000000.011 &nbsp; &nbsp; (note: should return ''true'')
:# &nbsp; &nbsp; 100.01, &nbsp; 100.011 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (note: should return ''false'')
:# &nbsp; &nbsp; 10000000000000.001 <big>/</big> 10000.0, &nbsp; 1000000000.0000001000
:# &nbsp; &nbsp; 0.001, &nbsp; 0.0010000001
:# &nbsp; &nbsp; 0.000000000000000000000101, &nbsp; 0.0
:# &nbsp; &nbsp; &nbsp;sqrt(2) * sqrt(2), &nbsp; &nbsp;2.0
:# &nbsp; &nbsp; -sqrt(2) * sqrt(2), &nbsp; -2.0
:# &nbsp; &nbsp; 3.14159265358979323846, &nbsp; 3.14159265358979324
<br/>
Answers should be true for the first example and false in the second, so that just rounding the numbers to a fixed number of decimals should not be enough. Otherwise answers may vary and still be correct. See the Python code for one type of solution.
<br><br>
__TOC__

View file

@ -0,0 +1,19 @@
BEGIN # test REAL values for approximate equality #
# returns TRUE if value is approximately equal to other, FALSE otherwide #
PROC approx equals = ( REAL value, REAL other, REAL epsilon )BOOL: ABS ( value - other ) < epsilon;
# shows the result of testing a for approximate equality with b #
PROC test = ( REAL a, b )VOID:
BEGIN
REAL epsilon = 1e-18;
print( ( a, ", ", b, " => ", IF approx equals( a, b, epsilon ) THEN "true" ELSE "false" FI, newline ) )
END # test # ;
# task test cases #
test( 100000000000000.01, 100000000000000.011 );
test( 100.01, 100.011 );
test( 10000000000000.001 / 10000.0, 1000000000.0000001000);
test( 0.001, 0.0010000001 );
test( 0.000000000000000000000101, 0.0 );
test( sqrt( 2 ) * sqrt( 2 ), 2.0 );
test( - sqrt( 2 ) * sqrt( 2 ), -2.0 );
test( 3.14159265358979323846, 3.14159265358979324 )
END

View file

@ -0,0 +1,23 @@
# syntax: GAWK -f APPROXIMATE_EQUALITY.AWK
# converted from C#
BEGIN {
epsilon = 1
while (1 + epsilon != 1) {
epsilon /= 2
}
printf("epsilon = %18.16g\n\n",epsilon)
main("100000000000000.01","100000000000000.011")
main("100.01","100.011")
main("10000000000000.001"/"10000.0","1000000000.0000001000")
main("0.001","0.0010000001")
main("0.000000000000000000000101","0.0")
main(sqrt(2.0)*sqrt(2.0),"2.0")
main(-sqrt(2.0)*sqrt(2.0),"-2.0")
main("3.14159265358979323846","3.14159265358979324")
exit(0)
}
function main(a,b, tmp) {
tmp = abs(a - b) < epsilon
printf("%d %27s %s\n",tmp,a,b)
}
function abs(x) { if (x >= 0) { return x } else { return -x } }

View file

@ -0,0 +1,46 @@
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Generic_Elementary_Functions;
procedure Main is
type Real is digits 18;
package Real_Funcs is new Ada.Numerics.Generic_Elementary_Functions(Real);
use Real_Funcs;
package Real_IO is new Ada.Text_IO.Float_IO(Real);
use Real_IO;
function Approx_Equal (Left : Real; Right : Real) return Boolean is
-- Calculate an epsilon value based upon the magnitude of the
-- maximum value of the two parameters
eps : Real := Real'Max(Left, Right) * 1.0e-9;
begin
if left > Right then
return Left - Right < eps;
else
return Right - Left < eps;
end if;
end Approx_Equal;
Type Index is (Left, Right);
type Pairs_List is array (Index) of Real;
type Pairs_Table is array(1..8) of Pairs_List;
Table : Pairs_Table;
begin
Table := ((100000000000000.01, 100000000000000.011),
(100.01, 100.011),
(10000000000000.001 / 10000.0, 1000000000.0000001000),
(0.001, 0.0010000001),
(0.000000000000000000000101, 0.0),
(sqrt(2.0) * sqrt(2.0), 2.0),
(-sqrt(2.0) * sqrt(2.0), -2.0),
(3.14159265358979323846, 3.14159265358979324));
for Pair of Table loop
Put(Item => Pair(Left), Exp => 0, Aft => 16, Fore => 6);
Put(" ");
Put(Item => Pair(Right), Exp => 0, Aft => 16, Fore => 6);
Put_Line(" " & Boolean'Image(Approx_Equal(Pair(Left), Pair(Right))));
end loop;
end Main;

View file

@ -0,0 +1,28 @@
#include <iomanip>
#include <iostream>
#include <cmath>
bool approxEquals(double a, double b, double e) {
return fabs(a - b) < e;
}
void test(double a, double b) {
constexpr double epsilon = 1e-18;
std::cout << std::setprecision(21) << a;
std::cout << ", ";
std::cout << std::setprecision(21) << b;
std::cout << " => ";
std::cout << approxEquals(a, b, epsilon) << '\n';
}
int main() {
test(100000000000000.01, 100000000000000.011);
test(100.01, 100.011);
test(10000000000000.001 / 10000.0, 1000000000.0000001000);
test(0.001, 0.0010000001);
test(0.000000000000000000000101, 0.0);
test(sqrt(2.0) * sqrt(2.0), 2.0);
test(-sqrt(2.0) * sqrt(2.0), -2.0);
test(3.14159265358979323846, 3.14159265358979324);
return 0;
}

View file

@ -0,0 +1,22 @@
using System;
public static class Program
{
public static void Main() {
Test(100000000000000.01, 100000000000000.011);
Test(100.01, 100.011);
Test(10000000000000.001 / 10000.0, 1000000000.0000001000);
Test(0.001, 0.0010000001);
Test(0.000000000000000000000101, 0.0);
Test(Math.Sqrt(2) * Math.Sqrt(2), 2.0);
Test(-Math.Sqrt(2) * Math.Sqrt(2), -2.0);
Test(3.14159265358979323846, 3.14159265358979324);
void Test(double a, double b) {
const double epsilon = 1e-18;
WriteLine($"{a}, {b} => {a.ApproxEquals(b, epsilon)}");
}
}
public static bool ApproxEquals(this double value, double other, double epsilon) => Math.Abs(value - other) < epsilon;
}

View file

@ -0,0 +1,24 @@
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
bool approxEquals(double value, double other, double epsilon) {
return fabs(value - other) < epsilon;
}
void test(double a, double b) {
double epsilon = 1e-18;
printf("%f, %f => %d\n", a, b, approxEquals(a, b, epsilon));
}
int main() {
test(100000000000000.01, 100000000000000.011);
test(100.01, 100.011);
test(10000000000000.001 / 10000.0, 1000000000.0000001000);
test(0.001, 0.0010000001);
test(0.000000000000000000000101, 0.0);
test(sqrt(2.0) * sqrt(2.0), 2.0);
test(-sqrt(2.0) * sqrt(2.0), -2.0);
test(3.14159265358979323846, 3.14159265358979324);
return 0;
}

View file

@ -0,0 +1,10 @@
(defun approx-equal (float1 float2 &optional (threshold 0.000001))
"Determine whether float1 and float2 are equal; THRESHOLD is the
maximum allowable difference between normalized significands of floats
with the same exponent. The significands are scaled appropriately
before comparison for floats with different exponents."
(multiple-value-bind (sig1 exp1 sign1) (decode-float float1)
(multiple-value-bind (sig2 exp2 sign2) (decode-float float2)
(let ((cmp1 (float-sign sign1 (scale-float sig1 (floor (- exp1 exp2) 2))))
(cmp2 (float-sign sign2 (scale-float sig2 (floor (- exp2 exp1) 2)))))
(< (abs (- cmp1 cmp2)) threshold)))))

View file

@ -0,0 +1,20 @@
import std.math;
import std.stdio;
auto approxEquals = (double a, double b, double epsilon) => abs(a - b) < epsilon;
void main() {
void test(double a, double b) {
double epsilon = 1e-18;
writefln("%.18f, %.18f => %s", a, b, a.approxEquals(b, epsilon));
}
test(100000000000000.01, 100000000000000.011);
test(100.01, 100.011);
test(10000000000000.001 / 10000.0, 1000000000.0000001000);
test(0.001, 0.0010000001);
test(0.000000000000000000000101, 0.0);
test(sqrt(2.0) * sqrt(2.0), 2.0);
test(-sqrt(2.0) * sqrt(2.0), -2.0);
test(3.14159265358979323846, 3.14159265358979324);
}

View file

@ -0,0 +1,34 @@
program Approximate_Equality;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Math;
const
EPSILON: Double = 1E-18;
procedure Test(a, b: Double; Expected: Boolean);
var
result: Boolean;
const
STATUS: array[Boolean] of string = ('FAIL', 'OK');
begin
result := SameValue(a, b, EPSILON);
Write(a, ' ', b, ' => ', result, ' '^I);
writeln(Expected, ^I, STATUS[Expected = result]);
end;
begin
Test(100000000000000.01, 100000000000000.011, True);
Test(100.01, 100.011, False);
Test(double(10000000000000.001) / double(10000.0), double(1000000000.0000001000),
False);
Test(0.001, 0.0010000001, False);
Test(0.000000000000000000000101, 0.0, True);
Test(double(Sqrt(2)) * double(Sqrt(2)), 2.0, False);
Test(-double(Sqrt(2)) * double(Sqrt(2)), -2.0, false);
Test(3.14159265358979323846, 3.14159265358979324, True);
Readln;
end.

View file

@ -0,0 +1,13 @@
USING: formatting generalizations kernel math math.functions ;
100000000000000.01 100000000000000.011
100.01 100.011
10000000000000.001 10000.0 /f 1000000000.0000001000
0.001 0.0010000001
0.000000000000000000000101 0.0
2 sqrt dup * 2.0
2 sqrt dup neg * -2.0
3.14159265358979323846 3.14159265358979324
[ 2dup -1e-15 ~ "%+47.30f %+47.30f -1e-15 ~ : %u\n" printf ]
2 8 mnapply

View file

@ -0,0 +1,5 @@
: test-f~ ( f1 f2 -- )
1e-18 \ epsilon
f~ \ AproximateEqual
if ." True" else ." False" then
;

View file

@ -0,0 +1,42 @@
program main
implicit none
integer :: i
double precision, allocatable :: vals(:)
vals = [ 100000000000000.01d0, 100000000000000.011d0, &
& 100.01d0, 100.011d0, &
& 10000000000000.001d0/10000d0, 1000000000.0000001000d0, &
& 0.001d0, 0.0010000001d0, &
& 0.000000000000000000000101d0, 0d0, &
& sqrt(2d0)*sqrt(2d0), 2d0, &
& -sqrt(2d0)*sqrt(2d0), -2d0, &
& 3.14159265358979323846d0, 3.14159265358979324d0 ]
do i = 1, size(vals)/2
print '(ES30.18, A, ES30.18, A, L)', vals(2*i-1), ' == ', vals(2*i), ' ? ', eq_approx(vals(2*i-1), vals(2*i))
end do
contains
logical function eq_approx(a, b, reltol, abstol)
!! is a approximately equal b?
double precision, intent(in) :: a, b
!! values to compare
double precision, intent(in), optional :: reltol, abstol
!! relative and absolute error thresholds.
!! defaults: epsilon, smallest non-denormal number
double precision :: rt, at
rt = epsilon(1d0)
at = tiny(1d0)
if (present(reltol)) rt = reltol
if (present(abstol)) at = abstol
eq_approx = abs(a - b) .le. max(rt * max(abs(a), abs(b)), at)
return
end function
end program

View file

@ -0,0 +1,25 @@
#include "string.bi"
Dim Shared As Double epsilon = 1
Sub eq_approx(a As Double,b As Double)
Dim As Boolean tmp = Abs(a - b) < epsilon
Print Using "& & &";tmp;a;b
End Sub
While (1 + epsilon <> 1)
epsilon /= 2
Wend
Print "epsilon = "; Format(epsilon, "0.000000000000000e-00")
Print
eq_approx(100000000000000.01, 100000000000000.011)
eq_approx(100.01, 100.011)
eq_approx(10000000000000.001/10000.0, 1000000000.0000001000)
eq_approx(0.001, 0.0010000001)
eq_approx(0.000000000000000000000101, 0.0)
eq_approx(Sqr(2)*Sqr(2), 2.0)
eq_approx(-Sqr(2)*Sqr(2), -2.0)
eq_approx(3.14159265358979323846, 3.14159265358979324)
Sleep

View file

@ -0,0 +1,26 @@
local fn DoublesAreApproxEqual( val1 as double, val2 as double, epsilon as double ) as CFStringRef
CFStringRef result = @"false"
if ( fn fabs( val1 - val2 ) < epsilon ) then result = @"true"
end fn = result
void local fn DoIt
long i
double epsilon = 1e-18, values(15)
values(0) = 100000000000000.01 : values(1) = 100000000000000.011
values(2) = 100.01 : values(3) = 100.011
values(4) = 10000000000000.001 / 10000.0 : values(5) = 1000000000.0000001000
values(6) = 0.001 : values(7) = 0.0010000001
values(8) = 0.000000000000000000000101 : values(9) = 0.0
values(10) = fn sqrt(2) * fn sqrt(2) : values(11) = 2.0
values(12) = -fn sqrt(2) * fn sqrt(2) : values(13) = -2.0
values(14) = 3.14159265358979323846 : values(15) = 3.14159265358979324
for i = 0 to 14 step 2
print values(i)@", "values(i+1)@" "fn DoublesAreApproxEqual( values(i), values(i+1), epsilon )
next
end fn
fn DoIt
HandleEvents

View file

@ -0,0 +1,55 @@
package main
import (
"fmt"
"log"
"math/big"
)
func max(a, b *big.Float) *big.Float {
if a.Cmp(b) > 0 {
return a
}
return b
}
func isClose(a, b *big.Float) bool {
relTol := big.NewFloat(1e-9) // same as default for Python's math.isclose() function
t := new(big.Float)
t.Sub(a, b)
t.Abs(t)
u, v, w := new(big.Float), new(big.Float), new(big.Float)
u.Mul(relTol, max(v.Abs(a), w.Abs(b)))
return t.Cmp(u) <= 0
}
func nbf(s string) *big.Float {
n, ok := new(big.Float).SetString(s)
if !ok {
log.Fatal("invalid floating point number")
}
return n
}
func main() {
root2 := big.NewFloat(2.0)
root2.Sqrt(root2)
pairs := [][2]*big.Float{
{nbf("100000000000000.01"), nbf("100000000000000.011")},
{nbf("100.01"), nbf("100.011")},
{nbf("0").Quo(nbf("10000000000000.001"), nbf("10000.0")), nbf("1000000000.0000001000")},
{nbf("0.001"), nbf("0.0010000001")},
{nbf("0.000000000000000000000101"), nbf("0.0")},
{nbf("0").Mul(root2, root2), nbf("2.0")},
{nbf("0").Mul(nbf("0").Neg(root2), root2), nbf("-2.0")},
{nbf("100000000000000003.0"), nbf("100000000000000004.0")},
{nbf("3.14159265358979323846"), nbf("3.14159265358979324")},
}
for _, pair := range pairs {
s := "≉"
if isClose(pair[0], pair[1]) {
s = "≈"
}
fmt.Printf("% 21.19g %s %- 21.19g\n", pair[0], s, pair[1])
}
}

View file

@ -0,0 +1,21 @@
class Approximate {
private static boolean approxEquals(double value, double other, double epsilon) {
return Math.abs(value - other) < epsilon
}
private static void test(double a, double b) {
double epsilon = 1e-18
System.out.printf("%f, %f => %s\n", a, b, approxEquals(a, b, epsilon))
}
static void main(String[] args) {
test(100000000000000.01, 100000000000000.011)
test(100.01, 100.011)
test(10000000000000.001 / 10000.0, 1000000000.0000001000)
test(0.001, 0.0010000001)
test(0.000000000000000000000101, 0.0)
test(Math.sqrt(2.0) * Math.sqrt(2.0), 2.0)
test(-Math.sqrt(2.0) * Math.sqrt(2.0), -2.0)
test(3.14159265358979323846, 3.14159265358979324)
}
}

View file

@ -0,0 +1,13 @@
class (Num a, Ord a, Eq a) => AlmostEq a where
eps :: a
infix 4 ~=
(~=) :: AlmostEq a => a -> a -> Bool
a ~= b = or [ a == b
, abs (a - b) < eps * abs(a + b)
, abs (a - b) < eps ]
instance AlmostEq Int where eps = 0
instance AlmostEq Integer where eps = 0
instance AlmostEq Double where eps = 1e-14
instance AlmostEq Float where eps = 1e-5

View file

@ -0,0 +1,17 @@
test :: [(Double, Double)]
test = [(100000000000000.01, 100000000000000.011)
,(100.01, 100.011)
,(10000000000000.001 / 10000.0, 1000000000.0000001000)
,(0.001, 0.0010000001)
,(0.000000000000000000000101, 0.0)
,(sqrt 2 * sqrt 2, 2.0)
,(-sqrt 2 * sqrt 2, -2.0)
,(3.141592653589793, 3.141592653589794)
,(3.141592653589, 3.141592653589794)]
-- requires import Text.Printf
main = mapM_ runTest test
where
runTest (a, b) = do
printf "%f == %f %v\n" a b (show $ a==b) :: IO ()
printf "%f ~= %f %v\n\n" a b (show $ a~=b)

View file

@ -0,0 +1,44 @@
NB. default comparison tolerance matches the python result
".;._2]0 :0
100000000000000.01 = 100000000000000.011
100.01 = 100.011
(10000000000000.001 % 10000.0) = 1000000000.0000001000
0.001 = 0.0010000001
0.000000000000000000000101 = 0.0
(= ([: *~ %:)) 2 NB. sqrt(2)*sqrt(2)
((= -)~ ([: (* -) %:)) 2 NB. -sqrt(2) * sqrt(2), -2.0
3.14159265358979323846 = 3.14159265358979324
)
1 0 1 0 0 1 1 1
NB. tolerance of 1e_12 matches the python result
".;._2]0 :0[CT=:1e_12
100000000000000.01 =!.CT 100000000000000.011
100.01 =!.CT 100.011
(10000000000000.001 % 10000.0) =!.CT 1000000000.0000001000
0.001 =!.CT 0.0010000001
0.000000000000000000000101 =!.CT 0.0
(=!.CT ([: *~ %:)) 2 NB. sqrt(2)*sqrt(2)
((=!.CT -)~ ([: (* -) %:)) 2 NB. -sqrt(2) * sqrt(2), -2.0
3.14159265358979323846 =!.CT 3.14159265358979324
)
1 0 1 0 0 1 1 1
NB. tight tolerance
".;._2]0 :0[CT=:1e_18
100000000000000.01 =!.CT 100000000000000.011
100.01 =!.CT 100.011
(10000000000000.001 % 10000.0) =!.CT 1000000000.0000001000
0.001 =!.CT 0.0010000001
0.000000000000000000000101 =!.CT 0.0
(=!.CT ([: *~ %:)) 2 NB. sqrt(2)*sqrt(2)
((=!.CT -)~ ([: (* -) %:)) 2 NB. -sqrt(2) * sqrt(2), -2.0
3.14159265358979323846 =!.CT 3.14159265358979324
)
1 0 0 0 0 0 0 1
2 (=!.1e_8) 9
|domain error
| 2(= !.1e_8)9

View file

@ -0,0 +1,21 @@
public class Approximate {
private static boolean approxEquals(double value, double other, double epsilon) {
return Math.abs(value - other) < epsilon;
}
private static void test(double a, double b) {
double epsilon = 1e-18;
System.out.printf("%f, %f => %s\n", a, b, approxEquals(a, b, epsilon));
}
public static void main(String[] args) {
test(100000000000000.01, 100000000000000.011);
test(100.01, 100.011);
test(10000000000000.001 / 10000.0, 1000000000.0000001000);
test(0.001, 0.0010000001);
test(0.000000000000000000000101, 0.0);
test(Math.sqrt(2.0) * Math.sqrt(2.0), 2.0);
test(-Math.sqrt(2.0) * Math.sqrt(2.0), -2.0);
test(3.14159265358979323846, 3.14159265358979324);
}
}

View file

@ -0,0 +1,25 @@
# Return whether the two numbers `a` and `b` are close.
# Closeness is determined by the `epsilon` parameter -
# the numbers are considered close if the difference between them
# is no more than epsilon * max(abs(a), abs(b)).
def isclose(a; b; epsilon):
((a - b) | fabs) <= (([(a|fabs), (b|fabs)] | max) * epsilon);
def lpad($len; $fill): tostring | ($len - length) as $l | ($fill * $l)[:$l] + .;
def lpad: lpad(20; " ");
# test values
def tv: [
{x: 100000000000000.01, y: 100000000000000.011 },
{x: 100.01, y: 100.011 },
{x: (10000000000000.001 / 10000.0), y: 1000000000.0000001000 },
{x: 0.001, y: 0.0010000001 },
{x: 0.000000000000000000000101, y: 0.0 },
{x: ((2|sqrt) * (2|sqrt)), y: 2.0 },
{x: (-(2|sqrt) * (2|sqrt)), y: -2.0 },
{x: 3.14159265358979323846, y: 3.14159265358979324 }
]
;
tv[] | "\(.x|lpad) \(if isclose(.x; .y; 1.0e-9) then " ≈ " else " ≉ " end) \(.y|lpad)"

View file

@ -0,0 +1,8 @@
100000000000000.02 ≈ 100000000000000.02
100.01 ≉ 100.011
1000000000.0000002 ≈ 1000000000.0000001
0.001 ≉ 0.0010000001
1.01e-22 ≉ 0
2.0000000000000004 ≈ 2
-2.0000000000000004 ≈ -2
3.141592653589793 ≈ 3.141592653589793

View file

@ -0,0 +1,12 @@
testvalues = [[100000000000000.01, 100000000000000.011],
[100.01, 100.011],
[10000000000000.001 / 10000.0, 1000000000.0000001000],
[0.001, 0.0010000001],
[0.000000000000000000000101, 0.0],
[sqrt(2) * sqrt(2), 2.0],
[-sqrt(2) * sqrt(2), -2.0],
[3.14159265358979323846, 3.14159265358979324]]
for (x, y) in testvalues
println(rpad(x, 21), " ≈ ", lpad(y, 22), ": ", x ≈ y)
end

View file

@ -0,0 +1,22 @@
import kotlin.math.abs
import kotlin.math.sqrt
fun approxEquals(value: Double, other: Double, epsilon: Double): Boolean {
return abs(value - other) < epsilon
}
fun test(a: Double, b: Double) {
val epsilon = 1e-18
println("$a, $b => ${approxEquals(a, b, epsilon)}")
}
fun main() {
test(100000000000000.01, 100000000000000.011)
test(100.01, 100.011)
test(10000000000000.001 / 10000.0, 1000000000.0000001000)
test(0.001, 0.0010000001)
test(0.000000000000000000000101, 0.0)
test(sqrt(2.0) * sqrt(2.0), 2.0)
test(-sqrt(2.0) * sqrt(2.0), -2.0)
test(3.14159265358979323846, 3.14159265358979324)
}

View file

@ -0,0 +1,21 @@
// Return whether the two numbers `a` and `b` are close.
// Closeness is determined by the `epsilon` parameter -
// the numbers are considered close if the difference between them
// is no more than epsilon * max(abs(a), abs(b)).
//
def isclose(a, b, epsilon):
return abs(a - b) <= max(abs(a), abs(b)) * epsilon
let tv = [
xy { 100000000000000.01, 100000000000000.011 },
xy { 100.01, 100.011 },
xy { 10000000000000.001 / 10000.0, 1000000000.0000001000 },
xy { 0.001, 0.0010000001 },
xy { 0.000000000000000000000101, 0.0 },
xy { sqrt(2.0) * sqrt(2.0), 2.0 },
xy { -sqrt(2.0) * sqrt(2.0), -2.0 },
xy { 3.14159265358979323846, 3.14159265358979324 }
]
for(tv) t:
print concat_string([string(t.x), if isclose(t.x, t.y, 1.0e-9): """ ≈ """ else: """ ≉ """, string(t.y)], "")

View file

@ -0,0 +1,21 @@
function approxEquals(value, other, epsilon)
return math.abs(value - other) < epsilon
end
function test(a, b)
local epsilon = 1e-18
print(string.format("%f, %f => %s", a, b, tostring(approxEquals(a, b, epsilon))))
end
function main()
test(100000000000000.01, 100000000000000.011);
test(100.01, 100.011)
test(10000000000000.001 / 10000.0, 1000000000.0000001000)
test(0.001, 0.0010000001)
test(0.000000000000000000000101, 0.0)
test(math.sqrt(2.0) * math.sqrt(2.0), 2.0)
test(-math.sqrt(2.0) * math.sqrt(2.0), -2.0)
test(3.14159265358979323846, 3.14159265358979324)
end
main()

View file

@ -0,0 +1,13 @@
ClearAll[CloseEnough]
CloseEnough[a_, b_, tol_] := Chop[a - b, tol] == 0
numbers = {
{100000000000000.01, 100000000000000.011},
{100.01, 100.011},
{10000000000000.001/10000.0, 1000000000.0000001000},
{0.001, 0.0010000001},
{0.000000000000000000000101, 0.0},
{Sqrt[2.0] Sqrt[2.0], 2.0}, {-Sqrt[2.0] Sqrt[2.0], -2.0},
{3.14159265358979323846, 3.14159265358979324}
};
(*And@@Flatten[Map[MachineNumberQ,numbers,{2}]]*)
{#1, #2, CloseEnough[#1, #2, 10^-9]} & @@@ numbers // Grid

View file

@ -0,0 +1,32 @@
from math import sqrt
import strformat
import strutils
const Tolerance = 1e-10
proc `~=`(a, b: float): bool =
## Check if "a" and "b" are close.
## We use a relative tolerance to compare the values.
result = abs(a - b) < max(abs(a), abs(b)) * Tolerance
proc compare(a, b: string) =
## Compare "a" and "b" transmitted as strings.
## Values are computed using "parseFloat".
let r = a.parseFloat() ~= b.parseFloat()
echo fmt"{a} ~= {b} is {r}"
proc compare(a: string; avalue: float; b: string) =
## Compare "a" and "b" transmitted as strings.
## The value of "a" is transmitted and not computed.
let r = avalue ~= b.parseFloat()
echo fmt"{a} ~= {b} is {r}"
compare("100000000000000.01", "100000000000000.011")
compare("100.01", "100.011")
compare("10000000000000.001 / 10000.0", 10000000000000.001 / 10000.0, "1000000000.0000001000")
compare("0.001", "0.0010000001")
compare("0.000000000000000000000101", "0.0")
compare("sqrt(2) * sqrt(2)", sqrt(2.0) * sqrt(2.0), "2.0")
compare("-sqrt(2) * sqrt(2)", -sqrt(2.0) * sqrt(2.0), "-2.0")
compare("3.14159265358979323846", "3.14159265358979324")

View file

@ -0,0 +1,17 @@
let approx_eq v1 v2 epsilon =
Float.abs (v1 -. v2) < epsilon
let test a b =
let epsilon = 1e-18 in
Printf.printf "%g, %g => %b\n" a b (approx_eq a b epsilon)
let () =
test 100000000000000.01 100000000000000.011;
test 100.01 100.011;
test (10000000000000.001 /. 10000.0) 1000000000.0000001000;
test 0.001 0.0010000001;
test 0.000000000000000000000101 0.0;
test ((sqrt 2.0) *. (sqrt 2.0)) 2.0;
test (-. (sqrt 2.0) *. (sqrt 2.0)) (-2.0);
test 3.14159265358979323846 3.14159265358979324;
;;

View file

@ -0,0 +1,70 @@
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.

View file

@ -0,0 +1,33 @@
use strict;
use warnings;
sub is_close {
my($a,$b,$eps) = @_;
$eps //= 15;
my $epse = $eps;
$epse++ if sprintf("%.${eps}f",$a) =~ /\./;
$epse++ if sprintf("%.${eps}f",$a) =~ /\-/;
my $afmt = substr((sprintf "%.${eps}f", $a), 0, $epse);
my $bfmt = substr((sprintf "%.${eps}f", $b), 0, $epse);
printf "%-5s %s ≅ %s\n", ($afmt eq $bfmt ? 'True' : 'False'), $afmt, $bfmt;
}
for (
[100000000000000.01, 100000000000000.011],
[100.01, 100.011],
[10000000000000.001 / 10000.0, 1000000000.0000001000],
[0.001, 0.0010000001],
[0.000000000000000000000101, 0.0],
[sqrt(2) * sqrt(2), 2.0],
[-sqrt(2) * sqrt(2), -2.0],
[100000000000000003.0, 100000000000000004.0],
[3.14159265358979323846, 3.14159265358979324]
) {
my($a,$b) = @$_;
is_close($a,$b);
}
print "\nTolerance may be adjusted.\n";
my $real_pi = 2 * atan2(1, 0);
my $roman_pi = 22/7;
is_close($real_pi,$roman_pi,$_) for <10 3>;

View file

@ -0,0 +1,22 @@
(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">dfmt</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"%g"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cfmt</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"%g"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">ca</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cfmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">cb</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cfmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">eqs</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ca</span><span style="color: #0000FF;">=</span><span style="color: #000000;">cb</span><span style="color: #0000FF;">?</span><span style="color: #008000;">""</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"NOT "</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">da</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dfmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">db</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dfmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%30s and\n%30s are %sapproximately equal\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">da</span><span style="color: #0000FF;">,</span><span style="color: #000000;">db</span><span style="color: #0000FF;">,</span><span style="color: #000000;">eqs</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">100000000000000.01</span><span style="color: #0000FF;">,</span><span style="color: #000000;">100000000000000.011</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%.3f"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">100.01</span><span style="color: #0000FF;">,</span><span style="color: #000000;">100.011</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%.3f"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10000000000000.001</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10000.0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1000000000.0000001000</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%.10f"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.001</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0.0010000001</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%.10f"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- both</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.001</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0.0010000001</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%.10f"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%.10f"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- ways</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.000000000000000000000101</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0.0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%f"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- both</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.000000000000000000000101</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0.0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%f"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%6f"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- ways</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)*</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span><span style="color: #000000;">2.0</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(-</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)*</span><span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),-</span><span style="color: #000000;">2.0</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3.14159265358979323846</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3.14159265358979324</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%.20f"</span><span style="color: #0000FF;">)</span>
<!--

View file

@ -0,0 +1,28 @@
double epsilon = 1e-18D;
void setup() {
testIsClose(100000000000000.01D, 100000000000000.011D, epsilon);
testIsClose(100.01D, 100.011D, epsilon);
testIsClose(10000000000000.001D / 10000.0D, 1000000000.0000001000D, epsilon);
testIsClose(0.001D, 0.0010000001D, epsilon);
testIsClose(0.000000000000000000000101D, 0.0D, epsilon);
testIsClose(Math.sqrt(2) * Math.sqrt(2), 2.0D, epsilon);
testIsClose(-Math.sqrt(2) * Math.sqrt(2), -2.0D, epsilon);
testIsClose(3.14159265358979323846D, 3.14159265358979324D, epsilon);
exit(); // all done
}
boolean isClose(double num1, double num2, double epsilon) {
return Math.abs(num2 - num1) <= epsilon;
}
void testIsClose(double num1, double num2, double epsilon) {
boolean result = isClose(num1, num2, epsilon);
if (result) {
println("True. ", num1, "is close to", num2);
} else {
println("False. ", num1, "is not close to", num2);
}
}

View file

@ -0,0 +1,15 @@
from numpy import sqrt
from math import isclose
testvalues = [[100000000000000.01, 100000000000000.011],
[100.01, 100.011],
[10000000000000.001 / 10000.0, 1000000000.0000001000],
[0.001, 0.0010000001],
[0.000000000000000000000101, 0.0],
[sqrt(2) * sqrt(2), 2.0],
[-sqrt(2) * sqrt(2), -2.0],
[3.14159265358979323846, 3.14159265358979324]]
for (x, y) in testvalues:
maybenot = "is" if isclose(x, y) else "is NOT"
print(x, maybenot, "approximately equal to ", y)

View file

@ -0,0 +1,13 @@
approxEq <- function(...) isTRUE(all.equal(...))
tests <- rbind(c(100000000000000.01, 100000000000000.011),
c(100.01, 100.011),
c(10000000000000.001 / 10000.0, 1000000000.0000001000),
c(0.001, 0.0010000001),
c(0.000000000000000000000101, 0.0),
c(sqrt(2) * sqrt(2), 2.0),
c(-sqrt(2) * sqrt(2), -2.0),
c(3.14159265358979323846, 3.14159265358979324))
results <- mapply(approxEq, tests[, 1], tests[, 2])
#All that remains is to print out our results in a presentable way:
printableTests <- format(tests, scientific = FALSE)
print(data.frame(x = printableTests[, 1], y = printableTests[, 2], Equal = results, row.names = paste0("Test ", 1:8, ": ")))

View file

@ -0,0 +1,30 @@
/*REXX program mimics an "approximately equal to" for comparing floating point numbers*/
numeric digits 15 /*what other FP hardware normally uses.*/
@.= /*assign default for the @ array. */
parse arg @.1 /*obtain optional argument from the CL.*/
if @.1='' | @.1=="," then do; @.1= 100000000000000.01 100000000000000.011
@.2= 100.01 100.011
@.3= 10000000000000.001 / 10000 1000000000.0000001000
@.4= 0.001 0.0010000001
@.5= 0.00000000000000000000101 0.0
@.6= sqrt(2) * sqrt(2) 2.0
@.7= -sqrt(2) * sqrt(2) '-2.0'
@.8= 3.14159265358979323846 3.14159265358979324
/* added ───► */ @.9= 100000000000000003.0 100000000000000004.0
end
do j=1 while @.j\=='' /*process CL argument or the array #s. */
say
say center(' processing pair ' j" ",71,'') /*display a title for the pair of #s. */
parse value @.j with a b /*extract two values from a pair of #s.*/
say 'A=' a /*display the value of A to the term.*/
say 'B=' b /* " " " " B " " " */
say right('A approximately equal to B?', 65) word("false true", 1 + approxEQ(a,b) )
end /*j*/ /* [↑] right─justify text & true/false*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
approxEQ: procedure; parse arg x,y; return x=y /*floating point compare with 15 digits*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); numeric digits; h=d+6
numeric form; m.=9; parse value format(x,2,1,,0) 'E0' with g "E" _ .; g=g *.5'e'_ %2
do j=0 while h>9; m.j=h; h=h%2+1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/; return g/1

View file

@ -0,0 +1,34 @@
#lang racket
(define ( a b [tolerance 1e-9])
(<= (abs (/ (- a b) (max a b))) tolerance))
(define all-tests
`(([100000000000000.01 100000000000000.011]
[100.01 100.011]
[,(/ 10000000000000.001 10000.0) 1000000000.0000001000]
[0.001 0.0010000001]
[0.000000000000000000000101 0.0]
[,(* (sqrt 2) (sqrt 2)) 2.0]
[,(* (- (sqrt 2)) (sqrt 2)) -2.0]
[100000000000000003.0 100000000000000004.0]
[3.14159265358979323846 3.14159265358979324])
([#e100000000000000.01 #e100000000000000.011]
[#e100.01 #e100.011]
[,(/ #e10000000000000.001 #e10000.0) #e1000000000.0000001000]
[#e0.001 #e0.0010000001]
[#e0.000000000000000000000101 #e0.0]
[,(* (sqrt 2) (sqrt 2)) #e2.0]
[,(* (- (sqrt 2)) (sqrt 2)) #e-2.0]
[100000000000000003 100000000000000004]
[#e3.14159265358979323846 #e3.14159265358979324])))
(define (format-num x)
(~a (~r x #:precision 30) #:min-width 50 #:align 'right))
(for ([tests (in-list all-tests)] [name '("inexact" "exact")])
(printf "~a:\n" name)
(for ([test (in-list tests)])
(match-define (list a b) test)
(printf "~a ~a: ~a\n" (format-num a) (format-num b) ( a b)))
(newline))

View file

@ -0,0 +1 @@
say 0.1 + 0.2 + 0.3 + 0.4 === 1.0000000000000000000000000000000000000000000000000000000000000000000000000; # True

View file

@ -0,0 +1,22 @@
for
100000000000000.01, 100000000000000.011,
100.01, 100.011,
10000000000000.001 / 10000.0, 1000000000.0000001000,
0.001, 0.0010000001,
0.000000000000000000000101, 0.0,
sqrt(2) * sqrt(2), 2.0,
-sqrt(2) * sqrt(2), -2.0,
100000000000000003.0, 100000000000000004.0,
3.14159265358979323846, 3.14159265358979324
-> $a, $b {
say "$a $b: ", $a $b;
}
say "\nTolerance may be adjusted.";
say 22/7, " ", π, ": ", 22/7 π;
{ # Localize the tolerance to only this block
my $*TOLERANCE = .001;
say 22/7, " ", π, ": ", 22/7 π;
}

View file

@ -0,0 +1,19 @@
let approx_eq = (v1, v2, epsilon) => {
abs_float (v1 -. v2) < epsilon
}
let test = (a, b) => {
let epsilon = 1e-18
Printf.printf("%g, %g => %b\n", a, b, approx_eq(a, b, epsilon))
}
{
test(100000000000000.01, 100000000000000.011)
test(100.01, 100.011)
test(10000000000000.001 /. 10000.0, 1000000000.0000001000)
test(0.001, 0.0010000001)
test(0.000000000000000000000101, 0.0)
test(sqrt(2.0) *. sqrt(2.0), 2.0)
test(-. sqrt(2.0) *. sqrt(2.0), (-2.0))
test(3.14159265358979323846, 3.14159265358979324)
}

View file

@ -0,0 +1,27 @@
require "bigdecimal"
testvalues = [[100000000000000.01, 100000000000000.011],
[100.01, 100.011],
[10000000000000.001 / 10000.0, 1000000000.0000001000],
[0.001, 0.0010000001],
[0.000000000000000000000101, 0.0],
[(2**0.5) * (2**0.5), 2.0],
[-(2**0.5) * (2**0.5), -2.0],
[BigDecimal("3.14159265358979323846"), 3.14159265358979324],
[Float::NAN, Float::NAN,],
[Float::INFINITY, Float::INFINITY],
]
class Numeric
def close_to?(num, tol = Float::EPSILON)
return true if self == num
return false if (self.to_f.nan? or num.to_f.nan?) # NaN is not even close to itself
return false if [self, num].count( Float::INFINITY) == 1 # Infinity is only close to itself
return false if [self, num].count(-Float::INFINITY) == 1
(self-num).abs <= tol * ([self.abs, num.abs].max)
end
end
testvalues.each do |a,b|
puts "#{a} #{a.close_to?(b) ? '≈' : '≉'} #{b}"
end

View file

@ -0,0 +1,26 @@
/// Return whether the two numbers `a` and `b` are close.
/// Closeness is determined by the `epsilon` parameter -
/// the numbers are considered close if the difference between them
/// is no more than epsilon * max(abs(a), abs(b)).
fn isclose(a: f64, b: f64, epsilon: f64) -> bool {
(a - b).abs() <= a.abs().max(b.abs()) * epsilon
}
fn main() {
fn sqrt(x: f64) -> f64 { x.sqrt() }
macro_rules! test {
($a: expr, $b: expr) => {
let operator = if isclose($a, $b, 1.0e-9) { '≈' } else { '≉' };
println!("{:>28} {} {}", stringify!($a), operator, stringify!($b))
}
}
test!(100000000000000.01, 100000000000000.011);
test!(100.01, 100.011);
test!(10000000000000.001/10000.0, 1000000000.0000001000);
test!(0.001, 0.0010000001);
test!(0.000000000000000000000101, 0.0);
test!( sqrt(2.0) * sqrt(2.0), 2.0);
test!(-sqrt(2.0) * sqrt(2.0), -2.0);
test!(3.14159265358979323846, 3.14159265358979324);
}

View file

@ -0,0 +1,20 @@
object Approximate extends App {
val (ok, notOk, ε) = ("👌", "❌", 1e-18d)
private def approxEquals(value: Double, other: Double, epsilon: Double) =
scala.math.abs(value - other) < epsilon
private def test(a: BigDecimal, b: BigDecimal, expected: Boolean): Unit = {
val result = approxEquals(a.toDouble, b.toDouble, ε)
println(f"$a%40.24f ≅ $b%40.24f => $result%5s ${if (expected == result) ok else notOk}")
}
test(BigDecimal("100000000000000.010"), BigDecimal("100000000000000.011"), true)
test(BigDecimal("100.01"), BigDecimal("100.011"), false)
test(BigDecimal(10000000000000.001 / 10000.0), BigDecimal("1000000000.0000001000"), false)
test(BigDecimal("0.001"), BigDecimal("0.0010000001"), false)
test(BigDecimal("0.000000000000000000000101"), BigDecimal(0), true)
test(BigDecimal(math.sqrt(2) * math.sqrt(2d)), BigDecimal(2.0), false)
test(BigDecimal(-Math.sqrt(2) * Math.sqrt(2)), BigDecimal(-2.0), false)
test(BigDecimal("3.14159265358979323846"), BigDecimal("3.14159265358979324"), true)
}

View file

@ -0,0 +1,16 @@
[
100000000000000.01, 100000000000000.011,
100.01, 100.011,
10000000000000.001 / 10000.0, 1000000000.0000001000,
0.001, 0.0010000001,
0.000000000000000000000101, 0.0,
sqrt(2) * sqrt(2), 2.0,
-sqrt(2) * sqrt(2), -2.0,
sqrt(-2) * sqrt(-2), -2.0,
cbrt(3)**3, 3,
cbrt(-3)**3, -3,
100000000000000003.0, 100000000000000004.0,
3.14159265358979323846, 3.14159265358979324
].each_slice(2, {|a,b|
say ("#{a} ≅ #{b}: ", a ≅ b)
})

View file

@ -0,0 +1,6 @@
var a = 100000000000000.01
var b = 100000000000000.011
# Rounding at 2 and 3 decimal places, respectively
say (round(a, -2) == round(b, -2)) # true
say (round(a, -3) == round(b, -3)) # false

View file

@ -0,0 +1,5 @@
var a = 22/7
var b = Num.pi
say ("22/7 ≅ π at 2 decimals: ", approx_cmp(a, b, -2) == 0)
say ("22/7 ≅ π at 3 decimals: ", approx_cmp(a, b, -3) == 0)

View file

@ -0,0 +1,2 @@
say (1.33333333.rat_approx == 4/3) # true
say (zeta(-5).rat_approx == -1/252) # true

View file

@ -0,0 +1,4 @@
for k in (3..19) {
var r = Str(Num.pi).first(k)
say ("rat_approx(#{r}) = ", Num(r).rat_approx.as_frac)
}

View file

@ -0,0 +1,11 @@
{ #(100000000000000.01 100000000000000.011) .
#(100.01 100.011) .
{10000000000000.001 / 10000.0 . 1000000000.0000001000} .
#(0.001 0.0010000001) .
#(0.000000000000000000000101 0.0) .
{ 2 sqrt * 2 sqrt . 2.0} .
{ 2 sqrt negated * 2 sqrt . -2.0} .
#(3.14159265358979323846 3.14159265358979324)
} pairsDo:[:val1 :val2 |
Stdout printCR: e'{val1} =~= {val2} -> {val1 isAlmostEqualTo:val2 nEpsilon:2}'
]

View file

@ -0,0 +1,68 @@
import Foundation
extension FloatingPoint {
@inlinable
public func isAlmostEqual(
to other: Self,
tolerance: Self = Self.ulpOfOne.squareRoot()
) -> Bool {
// tolerances outside of [.ulpOfOne,1) yield well-defined but useless results,
// so this is enforced by an assert rathern than a precondition.
assert(tolerance >= .ulpOfOne && tolerance < 1, "tolerance should be in [.ulpOfOne, 1).")
// The simple computation below does not necessarily give sensible
// results if one of self or other is infinite; we need to rescale
// the computation in that case.
guard self.isFinite && other.isFinite else {
return rescaledAlmostEqual(to: other, tolerance: tolerance)
}
// This should eventually be rewritten to use a scaling facility to be
// defined on FloatingPoint suitable for hypot and scaled sums, but the
// following is good enough to be useful for now.
let scale = max(abs(self), abs(other), .leastNormalMagnitude)
return abs(self - other) < scale*tolerance
}
@usableFromInline
internal func rescaledAlmostEqual(to other: Self, tolerance: Self) -> Bool {
// NaN is considered to be not approximately equal to anything, not even
// itself.
if self.isNaN || other.isNaN { return false }
if self.isInfinite {
if other.isInfinite { return self == other }
// Self is infinite and other is finite. Replace self with the binade
// of the greatestFiniteMagnitude, and reduce the exponent of other by
// one to compensate.
let scaledSelf = Self(sign: self.sign,
exponent: Self.greatestFiniteMagnitude.exponent,
significand: 1)
let scaledOther = Self(sign: .plus,
exponent: -1,
significand: other)
// Now both values are finite, so re-run the naive comparison.
return scaledSelf.isAlmostEqual(to: scaledOther, tolerance: tolerance)
}
// If self is finite and other is infinite, flip order and use scaling
// defined above, since this relation is symmetric.
return other.rescaledAlmostEqual(to: self, tolerance: tolerance)
}
}
let testCases = [
(100000000000000.01, 100000000000000.011),
(100.01, 100.011),
(10000000000000.001 / 10000.0, 1000000000.0000001000),
(0.001, 0.0010000001),
(0.000000000000000000000101, 0.0),
(sqrt(2) * sqrt(2), 2.0),
(-sqrt(2) * sqrt(2), -2.0),
(3.14159265358979323846, 3.14159265358979324)
]
for testCase in testCases {
print("\(testCase.0), \(testCase.1) => \(testCase.0.isAlmostEqual(to: testCase.1))")
}

View file

@ -0,0 +1,35 @@
catch {namespace delete test_almost_equal_decimal} ;# Start with a clean namespace
namespace eval test_almost_equal_decimal {
package require Tcl 8.5 ;# required by tcllib
package require math::decimal ;# from tcllib
namespace import ::math::decimal::* ;# for: setVariable, fromstr, and compare
array set yesno {0 Yes -1 No 1 No} ;# For nice output
# More info here: http://speleotrove.com/decimal/dax3274.html
# This puts the library into "simplified" mode. Which
# rounds the "decimal digits" in the coefficient to the
# number of digits that "precision" is set to.
setVariable extended 0
setVariable precision 9
set data {
{100000000000000.01 100000000000000.011}
{100.01 100.011}
{[expr {10000000000000.001 / 10000.0}] 1000000000.0000001000}
{0.001 0.0010000001}
{0.000000000000000000000101 0.0}
{[expr { sqrt(2) * sqrt(2)}] 2.0}
{[expr {-sqrt(2) * sqrt(2)}] -2.0}
{3.14159265358979323846 3.14159265358979324}
}
set data [subst $data] ;# resolves expressions in the list
foreach {a b} [join $data] {
set a_d [fromstr $a]
set b_d [fromstr $b]
puts [format "Is %26s %21s ? %4s." $a $b $yesno([compare $a_d $b_d])]
}
}

View file

@ -0,0 +1,43 @@
catch {namespace delete test_almost_equal_string} ;# Start with a clean namespace
namespace eval test_almost_equal_string {
package require Tcl 8.4 ;# ?Maybe earlier?
array set yesno {1 Yes 0 No} ;# For nice output
proc isClose {a b {prec 9}} {
proc toCoeff {n prec} {
set repr 40 ;# Chosen to be arbitrarily large to handle most cases
set long [format %0.${repr}f $n] ;# Take out of scientific notation
set map [string map {. {}} $long] ;# Remove decimal point
set trim [string trimleft $map 0] ;# Remove leading zeros
# restore string for comparison
set len [string length $trim]
if {$len < $prec} {
set trim "${trim}[string repeat 0 [expr ($prec+1)-$len]]"
}
# Round last decimal place
set rounded [format %0.f "[string range $trim 0 [expr {$prec-1}]].[string index $trim $prec]"]
return $rounded
}
set a_coeff [toCoeff $a $prec]
set b_coeff [toCoeff $b $prec]
return [expr {$a_coeff == $b_coeff}]
}
set data {
{100000000000000.01 100000000000000.011}
{100.01 100.011}
{[expr {10000000000000.001 / 10000.0}] 1000000000.0000001000}
{0.001 0.0010000001}
{0.000000000000000000000101 0.0}
{[expr { sqrt(2) * sqrt(2)}] 2.0}
{[expr {-sqrt(2) * sqrt(2)}] -2.0}
{3.14159265358979323846 3.14159265358979324}
}
set data [subst $data] ;# resolves expressions in the list
foreach {a b} [join $data] {
puts [format "Is %26s %21s ? %4s." $a $b $yesno([isClose $a $b])]
}
}

View file

@ -0,0 +1,26 @@
Imports System.Runtime.CompilerServices
Module Module1
<Extension()>
Function ApproxEquals(ByVal value As Double, other As Double, epsilon As Double)
Return Math.Abs(value - other) < epsilon
End Function
Sub Test(a As Double, b As Double)
Dim epsilon = 1.0E-18
Console.WriteLine($"{a}, {b} => {a.ApproxEquals(b, epsilon)}")
End Sub
Sub Main()
Test(100000000000000.02, 100000000000000.02)
Test(100.01, 100.011)
Test(10000000000000.002 / 10000.0, 1000000000.0000001)
Test(0.001, 0.0010000001)
Test(1.01E-22, 0.0)
Test(Math.Sqrt(2) * Math.Sqrt(2), 2.0)
Test(-Math.Sqrt(2) * Math.Sqrt(2), -2.0)
Test(3.1415926535897931, 3.1415926535897931)
End Sub
End Module

View file

@ -0,0 +1,17 @@
var tol = 1e-16
var pairs = [
[100000000000000.01, 100000000000000.011],
[100.01, 100.011],
[10000000000000.001 / 10000.0, 1000000000.0000001000],
[0.001, 0.0010000001],
[0.000000000000000000000101, 0.0],
[2.sqrt * 2.sqrt, 2.0],
[-2.sqrt * 2.sqrt, -2.0],
[3.14159265358979323846, 3.14159265358979324]
]
System.print("Approximate equality of test cases for a tolerance of %(tol):")
var i = 0
for (pair in pairs) {
i = i + 1
System.print(" %(i) -> %((pair[0] - pair[1]).abs < tol)")
}

View file

@ -0,0 +1,25 @@
func ApproxEqual(A, B); \Return 'true' if approximately equal
real A, B;
real Epsilon;
[Epsilon:= abs(A) * 1E-15;
return abs(A-B) < Epsilon;
];
real Data;
int I;
[Format(0, 16);
Data:=[ [100000000000000.01, 100000000000000.011], \should return true
[100.01, 100.011], \should return false
[10000000000000.001 / 10000.0, 1000000000.0000001000],
[0.001, 0.0010000001],
[0.000000000000000000000101, 0.0], \is undefined
[sqrt(2.0) * sqrt(2.0), 2.0],
[-1.0 * sqrt(2.0) * sqrt(2.0), -2.0], \-sqrt doesn't compile!
[3.14159265358979323846, 3.14159265358979324] ];
for I:= 0 to 7 do
[IntOut(0, I+1); Text(0, ". ");
RlOut(0, Data(I,0)); ChOut(0, ^ ); RlOut(0, Data(I,1));
Text(0, if ApproxEqual(Data(I,0), Data(I,1)) then " true" else " false");
CrLf(0);
];
]

View file

@ -0,0 +1,24 @@
// Rosetta Code problem: http://rosettacode.org/wiki/Approximate_equality
// by Jjuanhdez, 09/2022
epsilon = 1.0
while (1 + epsilon <> 1)
epsilon = epsilon / 2
wend
print "epsilon = ", epsilon
print
eq_approx(100000000000000.01, 100000000000000.011)
eq_approx(100.01, 100.011)
eq_approx(10000000000000.001/10000.0, 1000000000.0000001000)
eq_approx(0.001, 0.0010000001)
eq_approx(0.000000000000000000000101, 0.0)
eq_approx(sqrt(2)*sqrt(2), 2.0)
eq_approx(-sqrt(2)*sqrt(2), -2.0)
eq_approx(3.14159265358979323846, 3.14159265358979324)
end
sub eq_approx(a, b)
tmp = abs(a - b) < epsilon
print tmp, " ", a, " ", b
end sub

View file

@ -0,0 +1,17 @@
testValues:=T(
T(100000000000000.01,100000000000000.011),
T(100.01, 100.011),
T(10000000000000.001 / 10000.0, 1000000000.0000001),
T(0.001, 0.0010000001),
T(0.00000000000000000101, 0.0),
T( (2.0).sqrt()*(2.0).sqrt(), 2.0),
T( -(2.0).sqrt()*(2.0).sqrt(), -2.0),
T(100000000000000003.0, 100000000000000004.0),
T(3.14159265358979323846, 3.14159265358979324)
);
tolerance:=-1e-9; // <0 for relative comparison
foreach x,y in (testValues){
maybeNot:=( if(x.closeTo(y,tolerance)) " \u2248" else "!\u2248" );
println("% 25.19g %s %- 25.19g %g".fmt(x,maybeNot,y, (x-y).abs()));
}