From 4ba00805cb097cedd0d4c3df7abf7e00f844600f Mon Sep 17 00:00:00 2001 From: tompng Date: Wed, 8 Oct 2025 22:50:07 +0900 Subject: [PATCH] Fix bigdecimal spec Fix for new feature BigDecimal(float). Fix assertion of BigMath.log not to expect incorrect random digits to be appended. Fix assertion of too-strict precision and assertion that expecting precision to be too loose. Fix divmod, modulo and remainder assertion which was expecting a bug inconsistent with Float as a specification. Remove coerce expectation to add/sub/mult which was dropped because of a bug, and never implemented correctly in BigDecmal. --- library/bigdecimal/BigDecimal_spec.rb | 10 ++++++---- library/bigdecimal/add_spec.rb | 8 -------- library/bigdecimal/core_spec.rb | 7 +++++-- library/bigdecimal/divmod_spec.rb | 19 +++++++++++++------ library/bigdecimal/mult_spec.rb | 8 -------- library/bigdecimal/remainder_spec.rb | 8 +++++--- library/bigdecimal/shared/modulo.rb | 14 ++++++++++---- library/bigdecimal/shared/power.rb | 4 ++-- library/bigdecimal/sub_spec.rb | 8 -------- 9 files changed, 41 insertions(+), 45 deletions(-) diff --git a/library/bigdecimal/BigDecimal_spec.rb b/library/bigdecimal/BigDecimal_spec.rb index 45f5ebffc7..01772bf9af 100644 --- a/library/bigdecimal/BigDecimal_spec.rb +++ b/library/bigdecimal/BigDecimal_spec.rb @@ -156,8 +156,10 @@ BigDecimal("-12345.6E-1").should == -reference end - it "raises ArgumentError when Float is used without precision" do - -> { BigDecimal(1.0) }.should raise_error(ArgumentError) + version_is BigDecimal::VERSION, "3.3.0" do + it "allows Float without precision" do + BigDecimal(1.2).should == BigDecimal("1.2") + end end it "returns appropriate BigDecimal zero for signed zero" do @@ -259,8 +261,8 @@ def to_s; "cheese"; end end it "produces the expected result" do - @c.should == BigDecimal("-0.666667e-9") - @c.to_s.should == "-0.666667e-9" + @c.round(15).should == BigDecimal("-0.666667e-9") + @c.round(15).to_s.should == "-0.666667e-9" end it "produces the correct class for other arithmetic operators" do diff --git a/library/bigdecimal/add_spec.rb b/library/bigdecimal/add_spec.rb index 542713011d..9cdab7d910 100644 --- a/library/bigdecimal/add_spec.rb +++ b/library/bigdecimal/add_spec.rb @@ -73,14 +73,6 @@ # 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") diff --git a/library/bigdecimal/core_spec.rb b/library/bigdecimal/core_spec.rb index acee4dcf56..5097d70865 100644 --- a/library/bigdecimal/core_spec.rb +++ b/library/bigdecimal/core_spec.rb @@ -20,9 +20,12 @@ describe "BigDecimal#log" do it "handles high-precision Rational arguments" do - result = BigDecimal('0.22314354220170971436137296411949880462556361100856391620766259404746040597133837784E0') + # log(BigDecimal(r, 50), 50) + result1 = BigDecimal('0.22314354220170971436137296411949880462556361100856e0') + # log(BigDecimal(r, 1000), 50) + result2 = BigDecimal('0.22314354220170971436137296411949880462556361100853e0') r = Rational(1_234_567_890, 987_654_321) - BigMath.log(r, 50).should == result + [result1, result2].should include(BigMath.log(r, 50).mult(1, 50)) end end diff --git a/library/bigdecimal/divmod_spec.rb b/library/bigdecimal/divmod_spec.rb index 294f01cba0..c519783d14 100644 --- a/library/bigdecimal/divmod_spec.rb +++ b/library/bigdecimal/divmod_spec.rb @@ -154,12 +154,19 @@ class BigDecimal end end - it "returns an array of zero and the dividend if the divisor is Infinity" do - @regular_vals.each do |val| - array = val.divmod(@infinity) - array.length.should == 2 - array[0].should == @zero - array[1].should == val + version_is BigDecimal::VERSION, "3.3.0" do + it "returns an array of zero and the dividend or minus one and Infinity if the divisor is Infinity" do + @regular_vals.each do |val| + array = val.divmod(@infinity) + array.length.should == 2 + if val >= 0 + array[0].should == @zero + array[1].should == val + else + array[0].should == @one_minus + array[1].should == @infinity + end + end end end diff --git a/library/bigdecimal/mult_spec.rb b/library/bigdecimal/mult_spec.rb index b7f8044b0b..2353df9cb8 100644 --- a/library/bigdecimal/mult_spec.rb +++ b/library/bigdecimal/mult_spec.rb @@ -21,12 +21,4 @@ @e.mult(@one, 1).should be_close(@one, @tolerance) @e3_minus.mult(@one, 1).should be_close(0, @tolerance2) end - - describe "with Object" do - it "tries to coerce the other operand to self" do - object = mock("Object") - object.should_receive(:coerce).with(@e3_minus).and_return([@e3_minus, @e3_plus]) - @e3_minus.mult(object, 1).should == BigDecimal("9") - end - end end diff --git a/library/bigdecimal/remainder_spec.rb b/library/bigdecimal/remainder_spec.rb index bac5f37ba9..0eb06f7ef1 100644 --- a/library/bigdecimal/remainder_spec.rb +++ b/library/bigdecimal/remainder_spec.rb @@ -37,9 +37,11 @@ @neg_int.remainder(@pos_frac).should == @neg_int - @pos_frac * (@neg_int / @pos_frac).truncate end - it "returns NaN used with zero" do - @mixed.remainder(@zero).should.nan? - @zero.remainder(@zero).should.nan? + version_is BigDecimal::VERSION, "3.3.0" do + it "raises ZeroDivisionError used with zero" do + -> { @mixed.remainder(@zero) }.should raise_error(ZeroDivisionError) + -> { @zero.remainder(@zero) }.should raise_error(ZeroDivisionError) + end end it "returns zero if used on zero" do diff --git a/library/bigdecimal/shared/modulo.rb b/library/bigdecimal/shared/modulo.rb index aa5c5a640b..eeb030fd23 100644 --- a/library/bigdecimal/shared/modulo.rb +++ b/library/bigdecimal/shared/modulo.rb @@ -101,10 +101,16 @@ @infinity_minus.send(@method, @infinity).should.nan? end - it "returns the dividend if the divisor is Infinity" do - @one.send(@method, @infinity).should == @one - @one.send(@method, @infinity_minus).should == @one - @frac_2.send(@method, @infinity_minus).should == @frac_2 + version_is BigDecimal::VERSION, "3.3.0" do + it "returns the dividend if the divisor is Infinity and signs are same" do + @one.send(@method, @infinity).should == @one + (-@frac_2).send(@method, @infinity_minus).should == -@frac_2 + end + + it "returns the divisor if the divisor is Infinity and signs are different" do + (-@one).send(@method, @infinity).should == @infinity + @frac_2.send(@method, @infinity_minus).should == @infinity_minus + end end it "raises TypeError if the argument cannot be coerced to BigDecimal" do diff --git a/library/bigdecimal/shared/power.rb b/library/bigdecimal/shared/power.rb index 568a08589b..6dafb638e2 100644 --- a/library/bigdecimal/shared/power.rb +++ b/library/bigdecimal/shared/power.rb @@ -10,8 +10,8 @@ e = BigDecimal("1.00000000000000000000123456789") one = BigDecimal("1") ten = BigDecimal("10") - # The tolerance is dependent upon the size of BASE_FIG - tolerance = BigDecimal("1E-70") + # Accuracy is at least ndigits(== 30) + DOUBLE_FIG(== 16) + tolerance = BigDecimal("1E-46") ten_powers = BigDecimal("1E10000") pi = BigDecimal("3.14159265358979") e3_minus.send(@method, 2).should == e3_minus_power_2 diff --git a/library/bigdecimal/sub_spec.rb b/library/bigdecimal/sub_spec.rb index bddfec2186..3b62a0c794 100644 --- a/library/bigdecimal/sub_spec.rb +++ b/library/bigdecimal/sub_spec.rb @@ -35,14 +35,6 @@ @frac_1.sub(@frac_1, 1000000).should == @zero 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.sub(object, 1).should == BigDecimal("-0.9E15") - end - end - describe "with Rational" do it "produces a BigDecimal" do (@three - Rational(500, 2)).should == BigDecimal('-0.247e3')