Bug #16612
closedEnumerator::ArithmeticSequence#last with float range produces incorrect value
Description
Steps to reproduce
% ruby -e 'p ((0.24901079128550474)...(340.25008088980684)).step(34.00010700985213).last'
340.2500808898068
Expected result
Last value should match the value produced by the following:
ruby -e 'p ((0.24901079128550474)...(340.25008088980684)).step(34.00010700985213).to_a[-1]'
306.24997387995467
Environment
This was observed in versions 2.7.0
and 2.6.5
.
Updated by Eregon (Benoit Daloze) over 4 years ago
I'm unsure if the bug is in last
or in each
.
# last seems correct
[7] pry(main)> (0.24901079128550474r + 34.00010700985213r * 10).to_f
=> 340.2500808898068
[8] pry(main)> 340.25008088980684
=> 340.25008088980684
# Computing with 10 += seems correct too
[18] pry(main)> n=0.24901079128550474;
[19] pry(main)> 10.times {p n+=34.00010700985213}
34.249117801137636
68.24922481098977
102.2493318208419
136.24943883069403
170.24954584054615
204.24965285039826
238.24975986025038
272.2498668701025
306.2499738799546
340.2500808898067
=> 10
[20] pry(main)> 340.2500808898067 < 340.25008088980684
=> true
# But each/to_a gives different results:
[17] pry(main)> ((0.24901079128550474)...(340.25008088980684)).step(34.00010700985213).to_a
=> [0.24901079128550474,
34.249117801137636,
68.24922481098976,
102.24933182084189,
136.24943883069403,
170.24954584054615,
204.2496528503983,
238.24975986025044,
272.24986687010255,
306.24997387995467]
So I think last
is correct, and each
misses to yield the last element, probably due to accumulated errors.
Updated by nobu (Nobuyoshi Nakada) over 4 years ago
err
in ruby_float_step_size
seems too big in this case.
Updated by mrkn (Kenta Murata) over 4 years ago
- Status changed from Open to Assigned
- Assignee set to mrkn (Kenta Murata)
Updated by Anonymous over 4 years ago
Since past few days/weeks, the Redmine threading is broken. Can somebody
please look into this?
Thx.
Vít
Dne 07. 02. 20 v 9:58 muraken@gmail.com napsal(a):
Issue #16612 has been updated by mrkn (Kenta Murata).
Assignee set to mrkn (Kenta Murata)
Status changed from Open to Assigned
Bug #16612: Enumerator::ArithmeticSequence#last with float range produces incorrect value
https://bugs.ruby-lang.org/issues/16612#change-84193
- Author: bjfish (Brandon Fish)
- Status: Assigned
- Priority: Normal
- Assignee: mrkn (Kenta Murata)
- ruby -v: 2.7.0
- Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
Steps to reproduce
% ruby -e 'p ((0.24901079128550474)...(340.25008088980684)).step(34.00010700985213).last' 340.2500808898068
Expected result
Last value should match the value produced by the following:
ruby -e 'p ((0.24901079128550474)...(340.25008088980684)).step(34.00010700985213).to_a[-1]' 306.24997387995467
Environment
This was observed in versions2.7.0
and2.6.5
.
Updated by jeremyevans0 (Jeremy Evans) over 3 years ago
I've traced this to an off-by-one in ruby_float_step_size
. I've submitted a pull request to fix this: https://github.com/ruby/ruby/pull/4434
@Eregon (Benoit Daloze) Unfortunately, you can't get #each
to work like repeated edition without breaking backwards compatibility. It can change terminating loops into infinite loops in pathologic cases, and such pathological cases are part of the test suite. I tried that approach first (https://github.com/jeremyevans/ruby/commit/962edf65affe8ab1fc18b9a46317c543ef31bec8).
Updated by jeremyevans (Jeremy Evans) over 3 years ago
- Status changed from Assigned to Closed
Applied in changeset git|f516379853f36d143d820c55d5eeaa9fc410ef52.
Fix Enumerator::ArithmeticSequence handling of float ranges
Depending on the float range, there could be an off-by-one error,
where the last result that should be in the range was missed. Fix
this by checking if the computed value for the expected value
outside the range is still inside the range, and if so, increment
the step size.
Fixes [Bug #16612]