diff options
-rw-r--r-- | numeric.c | 20 | ||||
-rw-r--r-- | spec/ruby/core/range/step_spec.rb | 38 | ||||
-rw-r--r-- | test/ruby/test_float.rb | 11 |
3 files changed, 50 insertions, 19 deletions
@@ -2409,11 +2409,11 @@ ruby_float_step_size(double beg, double end, double unit, int excl) if (unit == 0) { return HUGE_VAL; } - n= (end - beg)/unit; - err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon; if (isinf(unit)) { return unit > 0 ? beg <= end : beg >= end; } + n= (end - beg)/unit; + err = (fabs(beg) + fabs(end) + fabs(end-beg)) / fabs(unit) * epsilon; if (err>0.5) err=0.5; if (excl) { if (n<=0) return 0; @@ -2421,10 +2421,26 @@ ruby_float_step_size(double beg, double end, double unit, int excl) n = 0; else n = floor(n - err); + if (beg < end) { + if ((n+1)*unit+beg < end) + n++; + } + else if (beg > end) { + if ((n+1)*unit+beg > end) + n++; + } } else { if (n<0) return 0; n = floor(n + err); + if (beg < end) { + if ((n+1)*unit+beg <= end) + n++; + } + else if (beg > end) { + if ((n+1)*unit+beg >= end) + n++; + } } return n+1; } diff --git a/spec/ruby/core/range/step_spec.rb b/spec/ruby/core/range/step_spec.rb index e284551ab3..1c2e30742c 100644 --- a/spec/ruby/core/range/step_spec.rb +++ b/spec/ruby/core/range/step_spec.rb @@ -207,10 +207,12 @@ describe "Range#step" do ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5]) end - it "returns Float values of 'step * n + begin < end'" do - (1.0...6.4).step(1.8) { |x| ScratchPad << x } - (1.0...55.6).step(18.2) { |x| ScratchPad << x } - ScratchPad.recorded.should eql([1.0, 2.8, 4.6, 1.0, 19.2, 37.4]) + ruby_version_is '3.1' do + it "returns Float values of 'step * n + begin < end'" do + (1.0...6.4).step(1.8) { |x| ScratchPad << x } + (1.0...55.6).step(18.2) { |x| ScratchPad << x } + ScratchPad.recorded.should eql([1.0, 2.8, 4.6, 1.0, 19.2, 37.4, 55.599999999999994]) + end end it "handles infinite values at either end" do @@ -457,19 +459,21 @@ describe "Range#step" do (-1.0...1.0).step(0.5).size.should == 4 end - it "returns the range size when there's no step_size" do - (-2..2).step.size.should == 5 - (-2.0..2.0).step.size.should == 5 - (-2..2.0).step.size.should == 5 - (-2.0..2).step.size.should == 5 - (1.0..6.4).step(1.8).size.should == 4 - (1.0..12.7).step(1.3).size.should == 10 - (-2...2).step.size.should == 4 - (-2.0...2.0).step.size.should == 4 - (-2...2.0).step.size.should == 4 - (-2.0...2).step.size.should == 4 - (1.0...6.4).step(1.8).size.should == 3 - (1.0...55.6).step(18.2).size.should == 3 + ruby_version_is '3.1' do + it "returns the range size when there's no step_size" do + (-2..2).step.size.should == 5 + (-2.0..2.0).step.size.should == 5 + (-2..2.0).step.size.should == 5 + (-2.0..2).step.size.should == 5 + (1.0..6.4).step(1.8).size.should == 4 + (1.0..12.7).step(1.3).size.should == 10 + (-2...2).step.size.should == 4 + (-2.0...2.0).step.size.should == 4 + (-2...2.0).step.size.should == 4 + (-2.0...2).step.size.should == 4 + (1.0...6.4).step(1.8).size.should == 3 + (1.0...55.6).step(18.2).size.should == 4 + end end it "returns nil with begin and end are String" do diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb index fbf0d87f8e..ca616456f1 100644 --- a/test/ruby/test_float.rb +++ b/test/ruby/test_float.rb @@ -882,6 +882,11 @@ class TestFloat < Test::Unit::TestCase end assert_equal([5.0, 4.0, 3.0, 2.0], 5.0.step(1.5, -1).to_a) + + assert_equal(11, ((0.24901079128550474)..(340.2500808898068)).step(34.00010700985213).to_a.size) + assert_equal(11, ((0.24901079128550474)..(340.25008088980684)).step(34.00010700985213).to_a.size) + assert_equal(11, ((-0.24901079128550474)..(-340.2500808898068)).step(-34.00010700985213).to_a.size) + assert_equal(11, ((-0.24901079128550474)..(-340.25008088980684)).step(-34.00010700985213).to_a.size) end def test_step2 @@ -893,6 +898,7 @@ class TestFloat < Test::Unit::TestCase a = rand b = a+rand*1000 s = (b - a) / 10 + b = a + s*10 seq = (a...b).step(s) assert_equal(10, seq.to_a.length, seq.inspect) end @@ -903,6 +909,11 @@ class TestFloat < Test::Unit::TestCase (1.0 ... e).step(1E-16) do |n| assert_operator(n, :<=, e) end + + assert_equal(10, ((0.24901079128550474)...(340.2500808898068)).step(34.00010700985213).to_a.size) + assert_equal(11, ((0.24901079128550474)...(340.25008088980684)).step(34.00010700985213).to_a.size) + assert_equal(10, ((-0.24901079128550474)...(-340.2500808898068)).step(-34.00010700985213).to_a.size) + assert_equal(11, ((-0.24901079128550474)...(-340.25008088980684)).step(-34.00010700985213).to_a.size) end def test_singleton_method |