Floating-point Comparison

0.1 + 0.2 ≠ 0.3

See Also

See also this article for a detailed discussion on comparing floating-point numbers.

Comparing floating-point numbers are tricky because they often fail miserably and unexpectedly.

Take the infamous 0.1 + 0.2 ≠ 0.3 example from most languages:

// JavaScript example

let x = 0.3;            // 0.3
let y = 0.1 + 0.2;      // 0.3?

console.log(x == y);    // false!

console.log(x);         // 0.3
console.log(y);         // 0.30000000000000004

Epsilon-Based Implementation

Warning

If the unchecked feature is enabled, then all floating-point comparisons are done as per IEEE 754 standard.

The IEEE 754 standard for floating-point arithmetic provides an epsilon value that can be used to compare floating-point numbers.

With max_diff = max(|x|, |y|) × epsilon, Rhai compares floating-point numbers based on the following:

operatoroperandsalgorithm
x == yhas zero|x - y| < epsilon
x == yboth non-zero|x - y| <
x != yhas zero|x - y|epsilon
x != yboth non-zero|x - y|max_diff
x > yhas zerox - yepsilon
x > yboth non-zerox - ymax_diff
x >= yhas zerox - y ≥ –epsilon
x >= yboth non-zerox - y ≥ –max_diff
x < yhas zeroy - xepsilon
x < yboth non-zeroy - xmax_diff
x <= yhas zeroy - x ≥ –epsilon
x <= yboth non-zeroy - x ≥ –max_diff

Casual Scripting Usage

For most scripts that casually compare floating-point numbers, the default behavior is sufficient to cover all bases:

let x = 1e-16;          // 0.0000000000000001
x > 0 == false;         // comparing with zero Just Works when value is very small
x == 0 == true;

let x = 1e-15;          // 0.000000000000001
x > 0 == true;          // comparing with zero when value above epsilon
x == 0 == false;

let x = 1e-28;          // 0.0000000000000000000000000001
let y = 1e-29;          // 0.00000000000000000000000000001, 10x smaller than 'x'
x > y == true;          // comparing very small numbers actually wide apart!

let x = 0.00000000000000000001;
let y = 0.000000000000000000010000000000000001;
x < y == false;         // difference is small enough for 'x' == 'y'

let y = 0.00000000000000000001000000000000001;
x < y = true;           // difference is not small enough for 'x' == 'y'