Project

General

Profile

Actions

Bug #16612

open

Enumerator::ArithmeticSequence#last with float range produces incorrect value

Added by bjfish (Brandon Fish) over 1 year ago. Updated 10 days ago.

Status:
Assigned
Priority:
Normal
Target version:
-
[ruby-core:97075]

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 1 year 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) about 1 year ago

err in ruby_float_step_size seems too big in this case.

Updated by mrkn (Kenta Murata) about 1 year ago

  • Assignee set to mrkn (Kenta Murata)
  • Status changed from Open to Assigned

Updated by Anonymous about 1 year 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 versions 2.7.0 and 2.6.5.

Updated by jeremyevans0 (Jeremy Evans) 10 days 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).

Actions

Also available in: Atom PDF