1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/spec/ruby/library/bigdecimal/add_spec.rb
2020-05-03 12:28:29 +02:00

193 lines
6.9 KiB
Ruby

require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require 'bigdecimal'
describe "BigDecimal#add" do
before :each do
@one = BigDecimal("1")
@zero = BigDecimal("0")
@two = BigDecimal("2")
@three = BigDecimal("3")
@ten = BigDecimal("10")
@eleven = BigDecimal("11")
@nan = BigDecimal("NaN")
@infinity = BigDecimal("Infinity")
@infinity_minus = BigDecimal("-Infinity")
@one_minus = BigDecimal("-1")
@frac_1 = BigDecimal("1E-99999")
@frac_2 = BigDecimal("0.9E-99999")
@frac_3 = BigDecimal("12345E10")
@frac_4 = BigDecimal("98765E10")
@dot_ones = BigDecimal("0.1111111111")
end
it "returns a + b with given precision" do
# documentation states, that precision ist optional, but it ain't,
@two.add(@one, 1).should == @three
@one .add(@two, 1).should == @three
@one.add(@one_minus, 1).should == @zero
@ten.add(@one, 2).should == @eleven
@zero.add(@one, 1).should == @one
@frac_2.add(@frac_1, 10000).should == BigDecimal("1.9E-99999")
@frac_1.add(@frac_1, 10000).should == BigDecimal("2E-99999")
@frac_3.add(@frac_4, 0).should == BigDecimal("0.11111E16")
@frac_3.add(@frac_4, 1).should == BigDecimal("0.1E16")
@frac_3.add(@frac_4, 2).should == BigDecimal("0.11E16")
@frac_3.add(@frac_4, 3).should == BigDecimal("0.111E16")
@frac_3.add(@frac_4, 4).should == BigDecimal("0.1111E16")
@frac_3.add(@frac_4, 5).should == BigDecimal("0.11111E16")
@frac_3.add(@frac_4, 6).should == BigDecimal("0.11111E16")
end
it "returns a + [Fixnum value] with given precision" do
(1..10).each {|precision|
@dot_ones.add(0, precision).should == BigDecimal("0." + "1" * precision)
}
BigDecimal("0.88").add(0, 1).should == BigDecimal("0.9")
end
it "returns a + [Bignum value] with given precision" do
bignum = 10000000000000000000
(1..20).each {|precision|
@dot_ones.add(bignum, precision).should == BigDecimal("0.1E20")
}
(21..30).each {|precision|
@dot_ones.add(bignum, precision).should == BigDecimal(
"0.10000000000000000000" + "1" * (precision - 20) + "E20")
}
end
# TODO:
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/17374
#
# This doesn't work on MRI and looks like a bug to me:
# one can use BigDecimal + Float, but not Bigdecimal.add(Float)
#
# it "returns a + [Float value] with given precision" do
# (1..10).each {|precision|
# @dot_ones.add(0.0, precision).should == BigDecimal("0." + "1" * precision)
# }
#
# BigDecimal("0.88").add(0.0, 1).should == BigDecimal("0.9")
# end
describe "with Object" do
it "tries to coerce the other operand to self" do
object = mock("Object")
object.should_receive(:coerce).with(@frac_3).and_return([@frac_3, @frac_4])
@frac_3.add(object, 1).should == BigDecimal("0.1E16")
end
end
describe "with Rational" do
it "produces a BigDecimal" do
(@three + Rational(500, 2)).should == BigDecimal("0.253e3")
end
end
it "favors the precision specified in the second argument over the global limit" do
BigDecimalSpecs.with_limit(1) do
BigDecimal('0.888').add(@zero, 3).should == BigDecimal('0.888')
end
BigDecimalSpecs.with_limit(2) do
BigDecimal('0.888').add(@zero, 1).should == BigDecimal('0.9')
end
end
it "uses the current rounding mode if rounding is needed" do
BigDecimalSpecs.with_rounding(BigDecimal::ROUND_UP) do
BigDecimal('0.111').add(@zero, 1).should == BigDecimal('0.2')
BigDecimal('-0.111').add(@zero, 1).should == BigDecimal('-0.2')
end
BigDecimalSpecs.with_rounding(BigDecimal::ROUND_DOWN) do
BigDecimal('0.999').add(@zero, 1).should == BigDecimal('0.9')
BigDecimal('-0.999').add(@zero, 1).should == BigDecimal('-0.9')
end
BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_UP) do
BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.9')
BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.9')
end
BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_DOWN) do
BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8')
BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8')
end
BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_EVEN) do
BigDecimal('0.75').add(@zero, 1).should == BigDecimal('0.8')
BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8')
BigDecimal('-0.75').add(@zero, 1).should == BigDecimal('-0.8')
BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8')
end
BigDecimalSpecs.with_rounding(BigDecimal::ROUND_CEILING) do
BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.9')
BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8')
end
BigDecimalSpecs.with_rounding(BigDecimal::ROUND_FLOOR) do
BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8')
BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.9')
end
end
it "uses the default ROUND_HALF_UP rounding if it wasn't explicitly changed" do
BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.9')
BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.9')
end
it "returns NaN if NaN is involved" do
@one.add(@nan, 10000).should.nan?
@nan.add(@one, 1).should.nan?
end
it "returns Infinity or -Infinity if these are involved" do
@zero.add(@infinity, 1).should == @infinity
@frac_2.add(@infinity, 1).should == @infinity
@one_minus.add(@infinity, 1).should == @infinity
@two.add(@infinity, 1).should == @infinity
@zero.add(@infinity_minus, 1).should == @infinity_minus
@frac_2.add(@infinity_minus, 1).should == @infinity_minus
@one_minus.add(@infinity_minus, 1).should == @infinity_minus
@two.add(@infinity_minus, 1).should == @infinity_minus
@infinity.add(@zero, 1).should == @infinity
@infinity.add(@frac_2, 1).should == @infinity
@infinity.add(@one_minus, 1).should == @infinity
@infinity.add(@two, 1).should == @infinity
@infinity_minus.add(@zero, 1).should == @infinity_minus
@infinity_minus.add(@frac_2, 1).should == @infinity_minus
@infinity_minus.add(@one_minus, 1).should == @infinity_minus
@infinity_minus.add(@two, 1).should == @infinity_minus
@infinity.add(@infinity, 10000).should == @infinity
@infinity_minus.add(@infinity_minus, 10000).should == @infinity_minus
end
it "returns NaN if Infinity + (- Infinity)" do
@infinity.add(@infinity_minus, 10000).should.nan?
@infinity_minus.add(@infinity, 10000).should.nan?
end
it "raises TypeError when adds nil" do
-> {
@one.add(nil, 10)
}.should raise_error(TypeError)
-> {
@one.add(nil, 0)
}.should raise_error(TypeError)
end
it "raises TypeError when precision parameter is nil" do
-> {
@one.add(@one, nil)
}.should raise_error(TypeError)
end
it "raises ArgumentError when precision parameter is negative" do
-> {
@one.add(@one, -10)
}.should raise_error(ArgumentError)
end
end