require 'test/unit' require_relative 'envutil' class TestFloat < Test::Unit::TestCase include EnvUtil def test_float assert_equal(2, 2.6.floor) assert_equal(-3, (-2.6).floor) assert_equal(3, 2.6.ceil) assert_equal(-2, (-2.6).ceil) assert_equal(2, 2.6.truncate) assert_equal(-2, (-2.6).truncate) assert_equal(3, 2.6.round) assert_equal(-2, (-2.4).truncate) assert_in_delta(13.4 % 1, 0.4, 0.0001) assert_equal(36893488147419111424, 36893488147419107329.0.to_i) end def nan_test(x,y) extend Test::Unit::Assertions assert_operator(x, :!=, y) assert_not_operator(x, :<, y) assert_not_operator(x, :>, y) assert_not_operator(x, :<=, y) assert_not_operator(x, :>=, y) end def test_nan nan = Float::NAN nan_test(nan, nan) nan_test(nan, 0) nan_test(nan, 1) nan_test(nan, -1) nan_test(nan, 1000) nan_test(nan, -1000) nan_test(nan, 1_000_000_000_000) nan_test(nan, -1_000_000_000_000) nan_test(nan, 100.0); nan_test(nan, -100.0); nan_test(nan, 0.001); nan_test(nan, -0.001); nan_test(nan, 1.0/0); nan_test(nan, -1.0/0); end def test_precision u = 3.7517675036461267e+17 v = sprintf("%.16e", u).to_f assert_in_delta(u, v, u.abs * Float::EPSILON) assert_in_delta(u, v, v.abs * Float::EPSILON) end def test_symmetry_bignum # [ruby-bugs-ja:118] a = 100000000000000000000000 b = 100000000000000000000000.0 assert_equal(a == b, b == a) end def test_cmp_int 100.times {|i| int0 = 1 << i [int0, -int0].each {|int| flt = int.to_f bigger = int + 1 smaller = int - 1 assert_operator(flt, :==, int) assert_operator(flt, :>, smaller) assert_operator(flt, :>=, smaller) assert_operator(flt, :<, bigger) assert_operator(flt, :<=, bigger) assert_equal(0, flt <=> int) assert_equal(-1, flt <=> bigger) assert_equal(1, flt <=> smaller) assert_operator(int, :==, flt) assert_operator(bigger, :>, flt) assert_operator(bigger, :>=, flt) assert_operator(smaller, :<, flt) assert_operator(smaller, :<=, flt) assert_equal(0, int <=> flt) assert_equal(-1, smaller <=> flt) assert_equal(1, bigger <=> flt) [ [int, flt + 0.5, bigger], [smaller, flt - 0.5, int] ].each {|smaller2, flt2, bigger2| next if flt2 == flt2.round assert_operator(flt2, :!=, smaller2) assert_operator(flt2, :!=, bigger2) assert_operator(flt2, :>, smaller2) assert_operator(flt2, :>=, smaller2) assert_operator(flt2, :<, bigger2) assert_operator(flt2, :<=, bigger2) assert_equal(-1, flt2 <=> bigger2) assert_equal(1, flt2 <=> smaller2) assert_operator(smaller2, :!=, flt2) assert_operator(bigger2, :!=, flt2) assert_operator(bigger2, :>, flt2) assert_operator(bigger2, :>=, flt2) assert_operator(smaller2, :<, flt2) assert_operator(smaller2, :<=, flt2) assert_equal(-1, smaller2 <=> flt2) assert_equal(1, bigger2 <=> flt2) } } } end def test_strtod a = Float("0") assert_in_delta(a, 0, Float::EPSILON) a = Float("0.0") assert_in_delta(a, 0, Float::EPSILON) a = Float("+0.0") assert_in_delta(a, 0, Float::EPSILON) a = Float("-0.0") assert_in_delta(a, 0, Float::EPSILON) a = Float("0.0000000000000000001") assert_not_equal(0.0, a) a = Float("+0.0000000000000000001") assert_not_equal(0.0, a) a = Float("-0.0000000000000000001") assert_not_equal(0.0, a) a = Float(".0") assert_in_delta(a, 0, Float::EPSILON) a = Float("+.0") assert_in_delta(a, 0, Float::EPSILON) a = Float("-.0") assert_in_delta(a, 0, Float::EPSILON) assert_raise(ArgumentError){Float("0.")} assert_raise(ArgumentError){Float("+0.")} assert_raise(ArgumentError){Float("-0.")} assert_raise(ArgumentError){Float(".")} assert_raise(ArgumentError){Float("+")} assert_raise(ArgumentError){Float("+.")} assert_raise(ArgumentError){Float("-")} assert_raise(ArgumentError){Float("-.")} assert_raise(ArgumentError){Float("1e")} assert_raise(ArgumentError){Float("1__1")} assert_raise(ArgumentError){Float("1.")} assert_raise(ArgumentError){Float("1.e+00")} assert_raise(ArgumentError){Float("0x1.p+0")} # add expected behaviour here. assert_equal(10, Float("1_0")) assert_equal([ 0.0].pack('G'), [Float(" 0x0p+0").to_f].pack('G')) assert_equal([-0.0].pack('G'), [Float("-0x0p+0").to_f].pack('G')) assert_equal(255.0, Float("0Xff")) assert_equal(1024.0, Float("0x1p10")) assert_equal(1024.0, Float("0x1p+10")) assert_equal(0.0009765625, Float("0x1p-10")) assert_equal(2.6881171418161356e+43, Float("0x1.3494a9b171bf5p+144")) assert_equal(-3.720075976020836e-44, Float("-0x1.a8c1f14e2af5dp-145")) assert_equal(31.0*2**1019, Float("0x0."+("0"*268)+"1fp2099")) assert_equal(31.0*2**1019, Float("0x0."+("0"*600)+"1fp3427")) assert_equal(-31.0*2**1019, Float("-0x0."+("0"*268)+"1fp2099")) assert_equal(-31.0*2**1019, Float("-0x0."+("0"*600)+"1fp3427")) suppress_warning do assert_equal(31.0*2**-1027, Float("0x1f"+("0"*268)+".0p-2099")) assert_equal(31.0*2**-1027, Float("0x1f"+("0"*600)+".0p-3427")) assert_equal(-31.0*2**-1027, Float("-0x1f"+("0"*268)+".0p-2099")) assert_equal(-31.0*2**-1027, Float("-0x1f"+("0"*600)+".0p-3427")) end end def test_divmod assert_equal([2, 3.5], 11.5.divmod(4)) assert_equal([-3, -0.5], 11.5.divmod(-4)) assert_equal([-3, 0.5], (-11.5).divmod(4)) assert_equal([2, -3.5], (-11.5).divmod(-4)) end def test_div assert_equal(2, 11.5.div(4)) assert_equal(-3, 11.5.div(-4)) assert_equal(-3, (-11.5).div(4)) assert_equal(2, (-11.5).div(-4)) end def test_modulo assert_equal(3.5, 11.5.modulo(4)) assert_equal(-0.5, 11.5.modulo(-4)) assert_equal(0.5, (-11.5).modulo(4)) assert_equal(-3.5, (-11.5).modulo(-4)) end def test_remainder assert_equal(3.5, 11.5.remainder(4)) assert_equal(3.5, 11.5.remainder(-4)) assert_equal(-3.5, (-11.5).remainder(4)) assert_equal(-3.5, (-11.5).remainder(-4)) end def test_to_s inf = Float::INFINITY assert_equal("Infinity", inf.to_s) assert_equal("-Infinity", (-inf).to_s) assert_equal("NaN", (inf / inf).to_s) assert_equal("1.0e+18", 1000_00000_00000_00000.0.to_s) bug3273 = '[ruby-core:30145]' [0.21611564636388508, 0.56].each do |f| s = f.to_s assert_equal(f, s.to_f, bug3273) assert_not_equal(f, s.chop.to_f, bug3273) end end def test_coerce assert_equal(Float, 1.0.coerce(1).first.class) end def test_plus assert_equal(4.0, 2.0.send(:+, 2)) assert_equal(4.0, 2.0.send(:+, (2**32).coerce(2).first)) assert_equal(4.0, 2.0.send(:+, 2.0)) assert_raise(TypeError) { 2.0.send(:+, nil) } end def test_minus assert_equal(0.0, 2.0.send(:-, 2)) assert_equal(0.0, 2.0.send(:-, (2**32).coerce(2).first)) assert_equal(0.0, 2.0.send(:-, 2.0)) assert_raise(TypeError) { 2.0.send(:-, nil) } end def test_mul assert_equal(4.0, 2.0.send(:*, 2)) assert_equal(4.0, 2.0.send(:*, (2**32).coerce(2).first)) assert_equal(4.0, 2.0.send(:*, 2.0)) assert_raise(TypeError) { 2.0.send(:*, nil) } end def test_div2 assert_equal(1.0, 2.0.send(:/, 2)) assert_equal(1.0, 2.0.send(:/, (2**32).coerce(2).first)) assert_equal(1.0, 2.0.send(:/, 2.0)) assert_raise(TypeError) { 2.0.send(:/, nil) } end def test_modulo2 assert_equal(0.0, 2.0.send(:%, 2)) assert_equal(0.0, 2.0.send(:%, (2**32).coerce(2).first)) assert_equal(0.0, 2.0.send(:%, 2.0)) assert_raise(TypeError) { 2.0.send(:%, nil) } end def test_modulo3 bug6048 = '[ruby-core:42726]' assert_equal(4.2, 4.2.send(:%, Float::INFINITY), bug6048) assert_equal(4.2, 4.2 % Float::INFINITY, bug6048) assert_is_minus_zero(-0.0 % 4.2) assert_is_minus_zero(-0.0.send :%, 4.2) assert_raise(ZeroDivisionError, bug6048) { 4.2.send(:%, 0.0) } assert_raise(ZeroDivisionError, bug6048) { 4.2 % 0.0 } assert_raise(ZeroDivisionError, bug6048) { 42.send(:%, 0) } assert_raise(ZeroDivisionError, bug6048) { 42 % 0 } end def test_divmod2 assert_equal([1.0, 0.0], 2.0.divmod(2)) assert_equal([1.0, 0.0], 2.0.divmod((2**32).coerce(2).first)) assert_equal([1.0, 0.0], 2.0.divmod(2.0)) assert_raise(TypeError) { 2.0.divmod(nil) } inf = Float::INFINITY assert_raise(ZeroDivisionError) {inf.divmod(0)} a, b = (2.0**32).divmod(1.0) assert_equal(2**32, a) assert_equal(0, b) end def test_pow assert_equal(1.0, 1.0 ** (2**32)) assert_equal(1.0, 1.0 ** 1.0) assert_raise(TypeError) { 1.0 ** nil } end def test_eql inf = Float::INFINITY nan = Float::NAN assert_operator(1.0, :eql?, 1.0) assert_operator(inf, :eql?, inf) assert_not_operator(nan, :eql?, nan) assert_not_operator(1.0, :eql?, nil) assert_equal(1.0, 1) assert_not_equal(1.0, 2**32) assert_not_equal(1.0, nan) assert_not_equal(1.0, nil) end def test_cmp inf = Float::INFINITY nan = Float::NAN assert_equal(0, 1.0 <=> 1.0) assert_equal(1, 1.0 <=> 0.0) assert_equal(-1, 1.0 <=> 2.0) assert_nil(1.0 <=> nil) assert_nil(1.0 <=> nan) assert_nil(nan <=> 1.0) assert_equal(0, 1.0 <=> 1) assert_equal(1, 1.0 <=> 0) assert_equal(-1, 1.0 <=> 2) assert_equal(-1, 1.0 <=> 2**32) assert_equal(1, inf <=> (Float::MAX.to_i*2)) assert_equal(-1, -inf <=> (-Float::MAX.to_i*2)) assert_equal(-1, (Float::MAX.to_i*2) <=> inf) assert_equal(1, (-Float::MAX.to_i*2) <=> -inf) bug3609 = '[ruby-core:31470]' def (pinf = Object.new).infinite?; +1 end def (ninf = Object.new).infinite?; -1 end def (fin = Object.new).infinite?; nil end nonum = Object.new assert_equal(0, inf <=> pinf, bug3609) assert_equal(1, inf <=> fin, bug3609) assert_equal(1, inf <=> ninf, bug3609) assert_nil(inf <=> nonum, bug3609) assert_equal(-1, -inf <=> pinf, bug3609) assert_equal(-1, -inf <=> fin, bug3609) assert_equal(0, -inf <=> ninf, bug3609) assert_nil(-inf <=> nonum, bug3609) assert_raise(ArgumentError) { 1.0 > nil } assert_raise(ArgumentError) { 1.0 >= nil } assert_raise(ArgumentError) { 1.0 < nil } assert_raise(ArgumentError) { 1.0 <= nil } end def test_zero_p assert_predicate(0.0, :zero?) assert_not_predicate(1.0, :zero?) end def test_infinite_p inf = Float::INFINITY assert_equal(1, inf.infinite?) assert_equal(-1, (-inf).infinite?) assert_nil(1.0.infinite?) end def test_finite_p inf = Float::INFINITY assert_not_predicate(inf, :finite?) assert_not_predicate(-inf, :finite?) assert_predicate(1.0, :finite?) end def test_floor_ceil_round_truncate assert_equal(1, 1.5.floor) assert_equal(2, 1.5.ceil) assert_equal(2, 1.5.round) assert_equal(1, 1.5.truncate) assert_equal(2, 2.0.floor) assert_equal(2, 2.0.ceil) assert_equal(2, 2.0.round) assert_equal(2, 2.0.truncate) assert_equal(-2, (-1.5).floor) assert_equal(-1, (-1.5).ceil) assert_equal(-2, (-1.5).round) assert_equal(-1, (-1.5).truncate) assert_equal(-2, (-2.0).floor) assert_equal(-2, (-2.0).ceil) assert_equal(-2, (-2.0).round) assert_equal(-2, (-2.0).truncate) inf = Float::INFINITY assert_raise(FloatDomainError) { inf.floor } assert_raise(FloatDomainError) { inf.ceil } assert_raise(FloatDomainError) { inf.round } assert_raise(FloatDomainError) { inf.truncate } end def test_round_with_precision assert_equal(1.100, 1.111.round(1)) assert_equal(1.110, 1.111.round(2)) assert_equal(11110.0, 11111.1.round(-1)) assert_equal(11100.0, 11111.1.round(-2)) assert_equal(10**300, 1.1e300.round(-300)) assert_equal(-10**300, -1.1e300.round(-300)) assert_equal(1.0e-300, 1.1e-300.round(300)) assert_equal(-1.0e-300, -1.1e-300.round(300)) bug5227 = '[ruby-core:39093]' assert_equal(42.0, 42.0.round(308), bug5227) assert_equal(1.0e307, 1.0e307.round(2), bug5227) assert_raise(TypeError) {1.0.round("4")} assert_raise(TypeError) {1.0.round(nil)} def (prec = Object.new).to_int; 2; end assert_equal(1.0, 0.998.round(prec)) end VS = [ 18446744073709551617.0, 18446744073709551616.0, 18446744073709551615.8, 18446744073709551615.5, 18446744073709551615.2, 18446744073709551615.0, 18446744073709551614.0, 4611686018427387905.0, 4611686018427387904.0, 4611686018427387903.8, 4611686018427387903.5, 4611686018427387903.2, 4611686018427387903.0, 4611686018427387902.0, 4294967297.0, 4294967296.0, 4294967295.8, 4294967295.5, 4294967295.2, 4294967295.0, 4294967294.0, 1073741825.0, 1073741824.0, 1073741823.8, 1073741823.5, 1073741823.2, 1073741823.0, 1073741822.0, -1073741823.0, -1073741824.0, -1073741824.2, -1073741824.5, -1073741824.8, -1073741825.0, -1073741826.0, -4294967295.0, -4294967296.0, -4294967296.2, -4294967296.5, -4294967296.8, -4294967297.0, -4294967298.0, -4611686018427387903.0, -4611686018427387904.0, -4611686018427387904.2, -4611686018427387904.5, -4611686018427387904.8, -4611686018427387905.0, -4611686018427387906.0, -18446744073709551615.0, -18446744073709551616.0, -18446744073709551616.2, -18446744073709551616.5, -18446744073709551616.8, -18446744073709551617.0, -18446744073709551618.0, ] def test_truncate VS.each {|f| i = f.truncate assert_equal(i, f.to_i) if f < 0 assert_operator(i, :<, 0) else assert_operator(i, :>, 0) end assert_operator(i.abs, :<=, f.abs) d = f.abs - i.abs assert_operator(0, :<=, d) assert_operator(d, :<, 1) } end def test_ceil VS.each {|f| i = f.ceil if f < 0 assert_operator(i, :<, 0) else assert_operator(i, :>, 0) end assert_operator(i, :>=, f) d = f - i assert_operator(-1, :<, d) assert_operator(d, :<=, 0) } end def test_floor VS.each {|f| i = f.floor if f < 0 assert_operator(i, :<, 0) else assert_operator(i, :>, 0) end assert_operator(i, :<=, f) d = f - i assert_operator(0, :<=, d) assert_operator(d, :<, 1) } end def test_round VS.each {|f| msg = "round(#{f})" i = f.round if f < 0 assert_operator(i, :<, 0, msg) else assert_operator(i, :>, 0, msg) end d = f - i assert_operator(-0.5, :<=, d, msg) assert_operator(d, :<=, 0.5, msg) } end def test_Float assert_in_delta(0.125, Float("0.1_2_5"), 0.00001) assert_in_delta(0.125, "0.1_2_5__".to_f, 0.00001) assert_equal(1, suppress_warning {Float(([1] * 10000).join)}.infinite?) assert_not_predicate(Float(([1] * 10000).join("_")), :infinite?) # is it really OK? assert_raise(ArgumentError) { Float("1.0\x001") } assert_equal(15.9375, Float('0xf.fp0')) assert_raise(ArgumentError) { Float('0x') } assert_equal(15, Float('0xf')) assert_equal(15, Float('0xfp0')) assert_raise(ArgumentError) { Float('0xfp') } assert_raise(ArgumentError) { Float('0xf.') } assert_raise(ArgumentError) { Float('0xf.p') } assert_raise(ArgumentError) { Float('0xf.p0') } assert_raise(ArgumentError) { Float('0xf.f') } assert_raise(ArgumentError) { Float('0xf.fp') } assert_equal(Float::INFINITY, Float('0xf.fp1000000000000000')) assert_equal(1, suppress_warning {Float("1e10_00")}.infinite?) assert_raise(TypeError) { Float(nil) } o = Object.new def o.to_f; inf = Float::INFINITY; inf/inf; end assert_predicate(Float(o), :nan?) end def test_invalid_str bug4310 = '[ruby-core:34820]' assert_raise(ArgumentError, bug4310) {under_gc_stress {Float('a'*10000)}} end def test_num2dbl assert_raise(ArgumentError) do 1.0.step(2.0, "0.5") {} end assert_raise(TypeError) do 1.0.step(2.0, nil) {} end end def test_sleep_with_Float assert_nothing_raised("[ruby-core:23282]") do sleep(0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1) end end def test_step 1000.times do a = rand b = a+rand*1000 s = (b - a) / 10 assert_equal(11, (a..b).step(s).to_a.length) end (1.0..12.7).step(1.3).each do |n| assert_operator(n, :<=, 12.7) end assert_equal([5.0, 4.0, 3.0, 2.0], 5.0.step(1.5, -1).to_a) end def test_step2 assert_equal([0.0], 0.0.step(1.0, Float::INFINITY).to_a) end def test_step_excl 1000.times do a = rand b = a+rand*1000 s = (b - a) / 10 assert_equal(10, (a...b).step(s).to_a.length) end assert_equal([1.0, 2.9, 4.8, 6.699999999999999], (1.0...6.8).step(1.9).to_a) e = 1+1E-12 (1.0 ... e).step(1E-16) do |n| assert_operator(n, :<=, e) end end def test_singleton_method # flonum on 64bit platform assert_raise(TypeError) { a = 1.0; def a.foo; end } # always not flonum assert_raise(TypeError) { a = Float::INFINITY; def a.foo; end } end def test_long_string assert_separately([], <<-'end;') assert_in_epsilon(10.0, ("1."+"1"*300000).to_f*9) end; end def test_next_float smallest = 0.0.next_float assert_equal(-Float::MAX, (-Float::INFINITY).next_float) assert_operator(-Float::MAX, :<, (-Float::MAX).next_float) assert_equal(Float::EPSILON/2, (-1.0).next_float + 1.0) assert_operator(0.0, :<, smallest) assert_operator([0.0, smallest], :include?, smallest/2) assert_equal(Float::EPSILON, 1.0.next_float - 1.0) assert_equal(Float::INFINITY, Float::MAX.next_float) assert_equal(Float::INFINITY, Float::INFINITY.next_float) assert(Float::NAN.next_float.nan?) end def test_prev_float smallest = 0.0.next_float assert_equal(-Float::INFINITY, (-Float::INFINITY).prev_float) assert_equal(-Float::INFINITY, (-Float::MAX).prev_float) assert_equal(-Float::EPSILON, (-1.0).prev_float + 1.0) assert_equal(-smallest, 0.0.prev_float) assert_operator([0.0, 0.0.prev_float], :include?, 0.0.prev_float/2) assert_equal(-Float::EPSILON/2, 1.0.prev_float - 1.0) assert_operator(Float::MAX, :>, Float::MAX.prev_float) assert_equal(Float::MAX, Float::INFINITY.prev_float) assert(Float::NAN.prev_float.nan?) end def test_next_prev_float_zero z = 0.0.next_float.prev_float assert_equal(0.0, z) assert_equal(Float::INFINITY, 1.0/z) z = 0.0.prev_float.next_float assert_equal(0.0, z) assert_equal(-Float::INFINITY, 1.0/z) end end