-
-
Save yennguyenh/2e81dc72b310cb9d886a82faf3d536ef to your computer and use it in GitHub Desktop.
Test cases for the relatively equality comparision method
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rails_helper' | |
require 'rantly/rspec_extensions' | |
require_relative '../../app/lib/math.rb' | |
RSpec.describe Math do | |
describe 'close?' do | |
context 'non numeric arguments' do | |
it 'raises exception' do | |
expect { Math.close?(nil, 0) }.to raise_error(ArgumentError) | |
expect { Math.close?(0, nil) }.to raise_error(ArgumentError) | |
end | |
end | |
context 'negative tolerance values' do | |
it 'raises exception' do | |
expect { Math.close?(0, 0, rel_tol: -1) }.to raise_error(ArgumentError) | |
expect { Math.close?(0, 0, abs_tol: -1) }.to raise_error(ArgumentError) | |
end | |
end | |
context 'Infinite values' do | |
it 'returns false when a is either side of Infinite value' do | |
expect(Math.close?(Float::INFINITY, 0)).to be_falsey | |
expect(Math.close?(-Float::INFINITY, 0)).to be_falsey | |
end | |
end | |
context 'integers' do | |
it 'returns true for same numbers' do | |
expect(Math.close?(0, 0)).to be_truthy | |
expect(Math.close?(10, 10)).to be_truthy | |
end | |
it 'returns false for different numbers' do | |
expect(Math.close?(10, 11)).to be_falsey | |
expect(Math.close?(0, 1)).to be_falsey | |
end | |
end | |
context 'large numbers' do | |
let (:exp10) { 1.0E10 } | |
it 'returns true for same positive numbers' do | |
expect(Math.close?(exp10, exp10 + 1)).to be_truthy | |
expect(Math.close?(exp10 + 1, exp10)).to be_truthy | |
end | |
it 'returns true for same negative numbers' do | |
expect(Math.close?(-exp10, -(exp10 + 1))).to be_truthy | |
expect(Math.close?(-(exp10 + 1), -exp10)).to be_truthy | |
end | |
it 'returns false for different positive numbers' do | |
expect(Math.close?(1000_000.0, 1000_001.0)).to be_falsey | |
expect(Math.close?(1000_001.0, 1000_000.0)).to be_falsey | |
end | |
it 'returns false for different negative numbers' do | |
expect(Math.close?(-1000_000.0, -1000_001.0)).to be_falsey | |
expect(Math.close?(-1000_001.0, -1000_000.0)).to be_falsey | |
end | |
end | |
context 'Numbers around ' do | |
it '1 returns true for same positive numbers' do | |
expect(Math.close?(1.000000001, 1.000000002)).to be_truthy | |
expect(Math.close?(1.000000002, 1.000000001)).to be_truthy | |
end | |
it '-1 returns true for same negative numbers' do | |
expect(Math.close?(-1.000000001, -1.000000002)).to be_truthy | |
expect(Math.close?(-1.000000002, -1.000000001)).to be_truthy | |
end | |
it '1 returns false for different positive numbers' do | |
expect(Math.close?(1.00000002, 1.00000001)).to be_falsey | |
expect(Math.close?(1.00000001, 1.00000002)).to be_falsey | |
end | |
it '-1 returns false for different negative numbers' do | |
expect(Math.close?(-1.00000002, -1.00000001)).to be_falsey | |
expect(Math.close?(-1.00000001, -1.00000002)).to be_falsey | |
end | |
end | |
context 'Numbers between 1 and 0' do | |
let (:absolute_tolerance) { 1.0E-14 } | |
it 'returns true for same positive numbers' do | |
expect(Math.close?(1000001.0E-15, 1000002.0E-15, abs_tol: absolute_tolerance)).to be_truthy | |
expect(Math.close?(1000002.0E-15, 1000001.0E-15, abs_tol: absolute_tolerance)).to be_truthy | |
end | |
it 'returns true for same negative numbers' do | |
expect(Math.close?(-1000001.0E-15, -1000002.0E-15, abs_tol: absolute_tolerance)).to be_truthy | |
expect(Math.close?(-1000002.0E-15, -1000001.0E-15, abs_tol: absolute_tolerance)).to be_truthy | |
end | |
it 'returns false for different positive numbers' do | |
expect(Math.close?(1000010.0E-15, 1000020.0E-15, abs_tol: absolute_tolerance)).to be_falsey | |
expect(Math.close?(1000020.0E-15, 1000010.0E-15, abs_tol: absolute_tolerance)).to be_falsey | |
end | |
it 'returns false for different negative numbers' do | |
expect(Math.close?(-1000010.0E-15, -1000020.0E-15, abs_tol: absolute_tolerance)).to be_falsey | |
expect(Math.close?(-1000020.0E-15, -1000010.0E-15, abs_tol: absolute_tolerance)).to be_falsey | |
end | |
end | |
context 'Numbers with small differences away from 0' do | |
let (:absolute_tolerance) { 1.0E-7 } | |
it 'returns true' do | |
expect(Math.close?(0.3, 0.30000003, abs_tol: absolute_tolerance)).to be_truthy | |
expect(Math.close?(-0.3, -0.30000003, abs_tol: absolute_tolerance)).to be_truthy | |
end | |
end | |
context 'Involving zero' do | |
let (:high_absolute_tolerance) { 1.0E-41 } | |
let (:low_absolute_tolerance) { 1.0E-2 } | |
it 'returns true in case of zero absolute value' do | |
expect(Math.close?(0.0, 0.0)).to be_truthy | |
expect(Math.close?(0.0, -0.0)).to be_truthy | |
expect(Math.close?(-0.0, 0.0)).to be_truthy | |
end | |
it 'returns true in case of low accuracy required' do | |
# with low absolute tolerance - low accuracy | |
expect(Math.close?(0.00000001, 0.0, abs_tol: low_absolute_tolerance)).to be_truthy | |
expect(Math.close?(0.0, 0.00000001, abs_tol: low_absolute_tolerance)).to be_truthy | |
expect(Math.close?(-0.00000001, 0.0, abs_tol: low_absolute_tolerance)).to be_truthy | |
expect(Math.close?(0.0, -0.00000001, abs_tol: low_absolute_tolerance)).to be_truthy | |
expect(Math.close?(0.0, 1E-40, abs_tol: low_absolute_tolerance)).to be_truthy | |
expect(Math.close?(1E-40, 0.0, abs_tol: low_absolute_tolerance)).to be_truthy | |
end | |
it 'return false in case of high accuracy required' do | |
# with high absolute tolerance - high accuracy | |
expect(Math.close?(0.00000001, 0.0, abs_tol: high_absolute_tolerance)).to be_falsey | |
expect(Math.close?(0.0, 0.00000001, abs_tol: high_absolute_tolerance)).to be_falsey | |
expect(Math.close?(-0.00000001, 0.0, abs_tol: high_absolute_tolerance)).to be_falsey | |
expect(Math.close?(0.0, -0.00000001, abs_tol: high_absolute_tolerance)).to be_falsey | |
expect(Math.close?(0.0, 1E-40, abs_tol: high_absolute_tolerance)).to be_falsey | |
expect(Math.close?(1E-40, 0.0, abs_tol: high_absolute_tolerance)).to be_falsey | |
end | |
end | |
context 'Numbers on opposite sides of 0' do | |
let (:minus_exp9) { 1.0E-9 } | |
let (:min_value) { 10**Float::MIN_EXP } | |
let (:high_absolute_tolerance) { 1.0E-307 } | |
it 'returns false' do | |
expect(Math.close?(1 + minus_exp9, -1.0)).to be_falsey | |
expect(Math.close?(-1.0, 1 + minus_exp9)).to be_falsey | |
expect(Math.close?(-(1 + minus_exp9), 1.0)).to be_falsey | |
expect(Math.close?(1.0, -(1 + minus_exp9))).to be_falsey | |
end | |
it 'return true in case of numbers near zero' do | |
expect(Math.close?(10 * min_value, 10 * -min_value, abs_tol: high_absolute_tolerance)).to be_truthy | |
end | |
end | |
context 'Numbers very close to zero' do | |
let (:min_value) { 10**Float::MIN_EXP } | |
let (:minus_exp9) { 1.0E-9 } | |
let (:high_absolute_tolerance) { 1.0E-40 } | |
it 'return true' do | |
expect(Math.close?(min_value, min_value, abs_tol: high_absolute_tolerance)).to be_truthy | |
expect(Math.close?(min_value, -min_value, abs_tol: high_absolute_tolerance)).to be_truthy | |
expect(Math.close?(-min_value, min_value, abs_tol: high_absolute_tolerance)).to be_truthy | |
expect(Math.close?(min_value, 0, abs_tol: high_absolute_tolerance)).to be_truthy | |
expect(Math.close?(0, min_value, abs_tol: high_absolute_tolerance)).to be_truthy | |
expect(Math.close?(-min_value, 0, abs_tol: high_absolute_tolerance)).to be_truthy | |
expect(Math.close?(0, -min_value, abs_tol: high_absolute_tolerance)).to be_truthy | |
end | |
it 'returns false' do | |
expect(Math.close?(min_value, minus_exp9, abs_tol: high_absolute_tolerance)).to be_falsey | |
expect(Math.close?(-min_value, minus_exp9, abs_tol: high_absolute_tolerance)).to be_falsey | |
expect(Math.close?(minus_exp9, -min_value, abs_tol: high_absolute_tolerance)).to be_falsey | |
expect(Math.close?(minus_exp9, min_value, abs_tol: high_absolute_tolerance)).to be_falsey | |
end | |
end | |
context 'Exact number pairs' do | |
let (:exact_pairs) { [ | |
[2.0, 2.0], | |
[0.1E200, 0.1E200], | |
[1.123E-300, 1.123E-300], | |
[0.0, -0.0], | |
[345667, 345667], | |
[BigDecimal('1.0001'), BigDecimal('1.0001')] | |
] } | |
it 'return true' do | |
exact_pairs.each do |pair| | |
expect(Math.close?(pair[0], pair[1])).to be_truthy | |
end | |
end | |
end | |
context 'BigDecimal number pairs' do | |
let (:big_decimal_pairs) { [ | |
[BigDecimal('1.000000001'), BigDecimal('1.0')], | |
[BigDecimal('1.000000001e-20'), BigDecimal('1.0e-20')], | |
[BigDecimal('1.000000001e-100'), BigDecimal('1.0e-100')], | |
] } | |
it 'return true' do | |
big_decimal_pairs.each do |pair| | |
expect(Math.close?(pair[0], pair[1])).to be_truthy | |
end | |
end | |
it 'return false with higher accuracy' do | |
big_decimal_pairs.each do |pair| | |
expect(Math.close?(pair[0], pair[1], rel_tol: 1E-10)).to be_falsey | |
end | |
end | |
end | |
context 'Fraction number pairs' do | |
let (:fraction_pairs) { [ | |
[Rational(1, 1E9) + 1, Rational(1)], | |
[Rational(1, 3), Rational(0.3333333333)] | |
] } | |
it 'return true' do | |
fraction_pairs.each do |pair| | |
expect(Math.close?(pair[0], pair[1])).to be_truthy | |
end | |
end | |
it 'return false with higher accuracy' do | |
fraction_pairs.each do |pair| | |
expect(Math.close?(pair[0], pair[1], rel_tol: 1E-10)).to be_falsey | |
end | |
end | |
end | |
context 'randomly generated sorted integers' do | |
let(:candidates) do | |
Rantly { array(100) { [integer, integer] } } | |
end | |
it 'return false in case of 2 random integers' do | |
candidates.each do |pair| | |
a, b = [pair.max, pair.min] # biggest number first | |
expect(Math.close?(a, b)).to be_falsey | |
end | |
end | |
it 'return true in case of 2 identical integers' do | |
candidates.each do |pair| | |
a, b = [pair.max, pair.max] # biggest number first | |
expect(Math.close?(a, b)).to be_truthy | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment