summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numeric.c20
-rw-r--r--spec/ruby/core/range/step_spec.rb38
-rw-r--r--test/ruby/test_float.rb11
3 files changed, 50 insertions, 19 deletions
diff --git a/numeric.c b/numeric.c
index 17a401f7d7..d0538ca126 100644
--- a/numeric.c
+++ b/numeric.c
@@ -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