require 'test/unit' class TestFloat < Test::Unit::TestCase 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((13.4 % 1 - 0.4).abs < 0.0001) assert_equal(36893488147419111424, 36893488147419107329.0.to_i) end def nan_test(x,y) extend Test::Unit::Assertions assert(x != y) assert_equal(false, (x < y)) assert_equal(false, (x > y)) assert_equal(false, (x <= y)) assert_equal(false, (x >= y)) end def test_nan nan = 0.0/0 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_strtod a = Float("0") assert(a.abs < Float::EPSILON) a = Float("0.0") assert(a.abs < Float::EPSILON) a = Float("+0.0") assert(a.abs < Float::EPSILON) a = Float("-0.0") assert(a.abs < Float::EPSILON) a = Float("0.0000000000000000001") assert(a != 0.0) a = Float("+0.0000000000000000001") assert(a != 0.0) a = Float("-0.0000000000000000001") assert(a != 0.0) a = Float(".0") assert(a.abs < Float::EPSILON) a = Float("+.0") assert(a.abs < Float::EPSILON) a = Float("-.0") assert(a.abs < Float::EPSILON) 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")} # add expected behaviour here. assert_equal(10, Float("1_0")) 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 = 1.0 / 0.0 assert_equal("Infinity", inf.to_s) assert_equal("-Infinity", (-inf).to_s) assert_equal("NaN", (inf / inf).to_s) assert_equal("1.0e+14", 10000_00000_00000.0.to_s) 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_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 = 1.0 / 0.0 a, b = inf.divmod(0) assert(a.infinite?) assert(b.nan?) 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 = 1.0 / 0.0 nan = inf / inf assert(1.0.eql?(1.0)) assert(inf.eql?(inf)) assert(!(nan.eql?(nan))) assert(!(1.0.eql?(nil))) assert(1.0 == 1) assert(1.0 != 2**32) assert(1.0 != nan) assert(1.0 != nil) end def test_cmp inf = 1.0 / 0.0 nan = inf / inf 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_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(0.0.zero?) assert(!(1.0.zero?)) end def test_infinite_p inf = 1.0 / 0.0 assert(1, inf.infinite?) assert(1, (-inf).infinite?) assert_nil(1.0.infinite?) end def test_finite_p inf = 1.0 / 0.0 assert(!(inf.finite?)) assert(!((-inf).finite?)) assert(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 = 1.0/0.0 assert_raise(FloatDomainError) { inf.floor } assert_raise(FloatDomainError) { inf.ceil } assert_raise(FloatDomainError) { inf.round } assert_raise(FloatDomainError) { inf.truncate } 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)) end def test_induced_from assert_equal(1.0, Float.induced_from(1)) assert_equal(1.0, Float.induced_from(1.0)) assert_raise(TypeError) { Float.induced_from(nil) } 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| i = f.round if f < 0 assert_operator(i, :<, 0) else assert_operator(i, :>, 0) end d = f - i assert_operator(-0.5, :<=, d) assert_operator(d, :<=, 0.5) } 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(Float(([1] * 10000).join).infinite?) assert(!Float(([1] * 10000).join("_")).infinite?) # is it really OK? assert_raise(ArgumentError) { Float("1.0\x001") } assert(Float("1e10_00").infinite?) assert_raise(TypeError) { Float(nil) } o = Object.new def o.to_f; inf = 1.0/0.0; inf/inf; end assert(Float(o).nan?) end def test_num2dbl assert_raise(TypeError) do 1.0.step(2.0, "0.5") {} end assert_raise(TypeError) do 1.0.step(2.0, nil) {} end end end