Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Approximate-equality/00-META.yaml
Normal file
2
Task/Approximate-equality/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Approximate_equality
|
||||
32
Task/Approximate-equality/00-TASK.txt
Normal file
32
Task/Approximate-equality/00-TASK.txt
Normal 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''' may be approximately equal to '''100000000000000.011''',
|
||||
<br>even though '''100.01''' is not approximately equal to '''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:
|
||||
:# 100000000000000.01, 100000000000000.011 (note: should return ''true'')
|
||||
:# 100.01, 100.011 (note: should return ''false'')
|
||||
:# 10000000000000.001 <big>/</big> 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
|
||||
<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__
|
||||
|
||||
19
Task/Approximate-equality/ALGOL-68/approximate-equality.alg
Normal file
19
Task/Approximate-equality/ALGOL-68/approximate-equality.alg
Normal 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
|
||||
23
Task/Approximate-equality/AWK/approximate-equality.awk
Normal file
23
Task/Approximate-equality/AWK/approximate-equality.awk
Normal 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 } }
|
||||
46
Task/Approximate-equality/Ada/approximate-equality.ada
Normal file
46
Task/Approximate-equality/Ada/approximate-equality.ada
Normal 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;
|
||||
28
Task/Approximate-equality/C++/approximate-equality.cpp
Normal file
28
Task/Approximate-equality/C++/approximate-equality.cpp
Normal 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;
|
||||
}
|
||||
22
Task/Approximate-equality/C-sharp/approximate-equality.cs
Normal file
22
Task/Approximate-equality/C-sharp/approximate-equality.cs
Normal 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;
|
||||
}
|
||||
24
Task/Approximate-equality/C/approximate-equality.c
Normal file
24
Task/Approximate-equality/C/approximate-equality.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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)))))
|
||||
20
Task/Approximate-equality/D/approximate-equality.d
Normal file
20
Task/Approximate-equality/D/approximate-equality.d
Normal 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);
|
||||
}
|
||||
34
Task/Approximate-equality/Delphi/approximate-equality.delphi
Normal file
34
Task/Approximate-equality/Delphi/approximate-equality.delphi
Normal 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.
|
||||
13
Task/Approximate-equality/Factor/approximate-equality.factor
Normal file
13
Task/Approximate-equality/Factor/approximate-equality.factor
Normal 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
|
||||
5
Task/Approximate-equality/Forth/approximate-equality.fth
Normal file
5
Task/Approximate-equality/Forth/approximate-equality.fth
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
: test-f~ ( f1 f2 -- )
|
||||
1e-18 \ epsilon
|
||||
f~ \ AproximateEqual
|
||||
if ." True" else ." False" then
|
||||
;
|
||||
42
Task/Approximate-equality/Fortran/approximate-equality.f
Normal file
42
Task/Approximate-equality/Fortran/approximate-equality.f
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
55
Task/Approximate-equality/Go/approximate-equality.go
Normal file
55
Task/Approximate-equality/Go/approximate-equality.go
Normal 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])
|
||||
}
|
||||
}
|
||||
21
Task/Approximate-equality/Groovy/approximate-equality.groovy
Normal file
21
Task/Approximate-equality/Groovy/approximate-equality.groovy
Normal 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)
|
||||
}
|
||||
}
|
||||
13
Task/Approximate-equality/Haskell/approximate-equality-1.hs
Normal file
13
Task/Approximate-equality/Haskell/approximate-equality-1.hs
Normal 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
|
||||
17
Task/Approximate-equality/Haskell/approximate-equality-2.hs
Normal file
17
Task/Approximate-equality/Haskell/approximate-equality-2.hs
Normal 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)
|
||||
44
Task/Approximate-equality/J/approximate-equality.j
Normal file
44
Task/Approximate-equality/J/approximate-equality.j
Normal 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
|
||||
21
Task/Approximate-equality/Java/approximate-equality.java
Normal file
21
Task/Approximate-equality/Java/approximate-equality.java
Normal 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);
|
||||
}
|
||||
}
|
||||
25
Task/Approximate-equality/Jq/approximate-equality-1.jq
Normal file
25
Task/Approximate-equality/Jq/approximate-equality-1.jq
Normal 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)"
|
||||
8
Task/Approximate-equality/Jq/approximate-equality-2.jq
Normal file
8
Task/Approximate-equality/Jq/approximate-equality-2.jq
Normal 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
|
||||
12
Task/Approximate-equality/Julia/approximate-equality.julia
Normal file
12
Task/Approximate-equality/Julia/approximate-equality.julia
Normal 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
|
||||
22
Task/Approximate-equality/Kotlin/approximate-equality.kotlin
Normal file
22
Task/Approximate-equality/Kotlin/approximate-equality.kotlin
Normal 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)
|
||||
}
|
||||
|
|
@ -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)], "")
|
||||
21
Task/Approximate-equality/Lua/approximate-equality.lua
Normal file
21
Task/Approximate-equality/Lua/approximate-equality.lua
Normal 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()
|
||||
|
|
@ -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
|
||||
32
Task/Approximate-equality/Nim/approximate-equality.nim
Normal file
32
Task/Approximate-equality/Nim/approximate-equality.nim
Normal 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")
|
||||
17
Task/Approximate-equality/OCaml/approximate-equality.ocaml
Normal file
17
Task/Approximate-equality/OCaml/approximate-equality.ocaml
Normal 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;
|
||||
;;
|
||||
70
Task/Approximate-equality/Pascal/approximate-equality.pas
Normal file
70
Task/Approximate-equality/Pascal/approximate-equality.pas
Normal 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.
|
||||
33
Task/Approximate-equality/Perl/approximate-equality.pl
Normal file
33
Task/Approximate-equality/Perl/approximate-equality.pl
Normal 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>;
|
||||
22
Task/Approximate-equality/Phix/approximate-equality.phix
Normal file
22
Task/Approximate-equality/Phix/approximate-equality.phix
Normal 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>
|
||||
<!--
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
15
Task/Approximate-equality/Python/approximate-equality.py
Normal file
15
Task/Approximate-equality/Python/approximate-equality.py
Normal 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)
|
||||
13
Task/Approximate-equality/R/approximate-equality.r
Normal file
13
Task/Approximate-equality/R/approximate-equality.r
Normal 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, ": ")))
|
||||
30
Task/Approximate-equality/REXX/approximate-equality.rexx
Normal file
30
Task/Approximate-equality/REXX/approximate-equality.rexx
Normal 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
|
||||
34
Task/Approximate-equality/Racket/approximate-equality.rkt
Normal file
34
Task/Approximate-equality/Racket/approximate-equality.rkt
Normal 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))
|
||||
|
|
@ -0,0 +1 @@
|
|||
say 0.1 + 0.2 + 0.3 + 0.4 === 1.0000000000000000000000000000000000000000000000000000000000000000000000000; # True
|
||||
22
Task/Approximate-equality/Raku/approximate-equality-2.raku
Normal file
22
Task/Approximate-equality/Raku/approximate-equality-2.raku
Normal 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 ≅ π;
|
||||
}
|
||||
19
Task/Approximate-equality/ReScript/approximate-equality.re
Normal file
19
Task/Approximate-equality/ReScript/approximate-equality.re
Normal 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)
|
||||
}
|
||||
27
Task/Approximate-equality/Ruby/approximate-equality.rb
Normal file
27
Task/Approximate-equality/Ruby/approximate-equality.rb
Normal 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
|
||||
26
Task/Approximate-equality/Rust/approximate-equality.rust
Normal file
26
Task/Approximate-equality/Rust/approximate-equality.rust
Normal 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);
|
||||
}
|
||||
20
Task/Approximate-equality/Scala/approximate-equality.scala
Normal file
20
Task/Approximate-equality/Scala/approximate-equality.scala
Normal 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)
|
||||
}
|
||||
16
Task/Approximate-equality/Sidef/approximate-equality-1.sidef
Normal file
16
Task/Approximate-equality/Sidef/approximate-equality-1.sidef
Normal 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)
|
||||
})
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
say (1.33333333.rat_approx == 4/3) # true
|
||||
say (zeta(-5).rat_approx == -1/252) # true
|
||||
|
|
@ -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)
|
||||
}
|
||||
11
Task/Approximate-equality/Smalltalk/approximate-equality.st
Normal file
11
Task/Approximate-equality/Smalltalk/approximate-equality.st
Normal 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}'
|
||||
]
|
||||
68
Task/Approximate-equality/Swift/approximate-equality.swift
Normal file
68
Task/Approximate-equality/Swift/approximate-equality.swift
Normal 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))")
|
||||
}
|
||||
35
Task/Approximate-equality/Tcl/approximate-equality-1.tcl
Normal file
35
Task/Approximate-equality/Tcl/approximate-equality-1.tcl
Normal 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])]
|
||||
}
|
||||
}
|
||||
43
Task/Approximate-equality/Tcl/approximate-equality-2.tcl
Normal file
43
Task/Approximate-equality/Tcl/approximate-equality-2.tcl
Normal 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])]
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
17
Task/Approximate-equality/Wren/approximate-equality.wren
Normal file
17
Task/Approximate-equality/Wren/approximate-equality.wren
Normal 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)")
|
||||
}
|
||||
25
Task/Approximate-equality/XPL0/approximate-equality.xpl0
Normal file
25
Task/Approximate-equality/XPL0/approximate-equality.xpl0
Normal 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);
|
||||
];
|
||||
]
|
||||
24
Task/Approximate-equality/Yabasic/approximate-equality.basic
Normal file
24
Task/Approximate-equality/Yabasic/approximate-equality.basic
Normal 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
|
||||
17
Task/Approximate-equality/Zkl/approximate-equality.zkl
Normal file
17
Task/Approximate-equality/Zkl/approximate-equality.zkl
Normal 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()));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue