The Wayback Machine - https://web.archive.org/web/20210907114649/https://github.com/ruby/ruby/pull/4682
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Rational for Float#round with ndigits > 14 #4682

Merged
merged 1 commit into from Aug 6, 2021

Conversation

@jeremyevans
Copy link
Contributor

@jeremyevans jeremyevans commented Jul 26, 2021

ndigits higher than 14 can result in values that are slightly too
large due to floating point limitations. Converting to rational
for the calculation and then back to float fixes these issues.

Fixes [Bug #14635]
Fixes [Bug #17183]

Co-authored by: Yusuke Endoh [email protected]

ndigits higher than 14 can result in values that are slightly too
large due to floating point limitations.  Converting to rational
for the calculation and then back to float fixes these issues.

Fixes [Bug #14635]
Fixes [Bug #17183]

Co-authored by: Yusuke Endoh <[email protected]>
@jeremyevans jeremyevans requested a review from mame Jul 26, 2021
@marcandre
Copy link
Member

@marcandre marcandre commented Aug 5, 2021

Sorry, just saw this.
I'll have to look at this while less tired, but going through rationals (I realize I talked about this first) might not be the correct approach, as that rational can be smaller than the equivalent decimal representation.

@jeremyevans
Copy link
Contributor Author

@jeremyevans jeremyevans commented Aug 6, 2021

Sorry, just saw this.
I'll have to look at this while less tired, but going through rationals (I realize I talked about this first) might not be the correct approach, as that rational can be smaller than the equivalent decimal representation.

I'm open to other approaches. This isn't my area of expertise, I was just trying to get these bugs fixed based on patches already provided.

Do you have a case that still fails with the proposed approach (proving this approach doesn't go far enough)? Do you have a case that fails with the proposed approach but works with the current approach (proving the proposed approach introduces a regression)? If this causes regressions, we definitely shouldn't do it. If it fixes some cases but not others, but doesn't break any existing cases, it may still be worth applying. If you have an intuition that this approach isn't going to work for all cases, but cannot come up with a failing case, I'm willing to accept that and won't press for this to be merged, but it would be nicer to have proof that this approach has problems.

@marcandre
Copy link
Member

@marcandre marcandre commented Aug 6, 2021

I didn't try your patch, but IIUC, it uses Rational(self).round(n).to_f? If so, I suspect that (2.914e-17).round(20) would return 2.913e-17 instead of 2.914e-17, right?

I think the correct version would be Rational(self.to_s).round(n).to_f. I believe that this definition would also fix the issue for 291.4 in https://bugs.ruby-lang.org/issues/18018 (but more slowly).

Basically, for this rounding algorithm of floats, the convertion to a rational should be using the decimal notation instead of the base-2 representation. (e.g.: 291.4 => Rational(2914, 10) instead of 2563181506671411/8796093022208)

@jeremyevans
Copy link
Contributor Author

@jeremyevans jeremyevans commented Aug 6, 2021

I checked out this branch and ran p (2.914e-17).round(20) and it printed 2.914e-17. I'm not opposed to switching to the to_s route, but we should at least confirm it is necessary.

@marcandre
Copy link
Member

@marcandre marcandre commented Aug 6, 2021

Oh, my bad, I confused round with floor 🤦‍♂️.

@jeremyevans jeremyevans merged commit d16b68c into ruby:master Aug 6, 2021
72 checks passed
72 checks passed
@github-actions
BASERUBY (ruby-2.2)
Details
@github-actions
update-deps (ubuntu-20.04)
Details
@github-actions
CodeQL-Build CodeQL-Build
Details
@github-actions
gcc-11
Details
@github-actions
make (check, --jit)
Details
@github-actions
make (check)
Details
@github-actions
checks
Details
@github-actions
Rubyspec (ruby-2.7)
Details
@github-actions
make (check, ubuntu-20.04)
Details
@github-actions
make (check, windows-2019, 2019)
Details
@github-actions
make (check)
Details
@github-actions
BASERUBY (ruby-2.7)
Details
@github-actions
update-deps (macos-latest)
Details
@github-actions
gcc-10
Details
@github-actions
make (check, --jit-wait)
Details
@github-actions
Rubyspec (ruby-3.0)
Details
@github-actions
make (check, ubuntu-20.04, cppflags=-DRUBY_DEBUG)
Details
@github-actions
make (test-bundler-parallel)
Details
@github-actions
gcc-9
Details
@github-actions
make (test-bundler-parallel, ubuntu-20.04)
Details
@github-actions
gcc-8
Details
@github-actions
make (test-bundler-parallel, ubuntu-20.04, cppflags=-DRUBY_DEBUG)
Details
@github-actions
gcc-7
Details
@github-actions
make (test-bundled-gems, ubuntu-20.04)
Details
@github-actions
gcc-6
Details
@github-actions
make (test-bundled-gems, ubuntu-20.04, cppflags=-DRUBY_DEBUG)
Details
@github-actions
gcc-5
Details
@github-actions
make (test-all TESTS=--repeat-count=2, ubuntu-20.04)
Details
@github-actions
gcc-4.8
Details
@github-actions
clang-13
Details
@github-actions
clang-12
Details
@github-actions
clang-11
Details
@github-actions
clang-10
Details
@github-actions
clang-9
Details
@github-actions
clang-8
Details
@github-actions
clang-7
Details
@github-actions
clang-6.0
Details
@github-actions
clang-5.0
Details
@github-actions
clang-4.0
Details
@github-actions
clang-3.9
Details
@github-actions
aarch64-linux-gnu
Details
@github-actions
powerpc64le-linux-gnu
Details
@github-actions
s390x-linux-gnu
Details
@github-actions
x86_64-w64-mingw32
Details
@github-actions
c++98
Details
@github-actions
c++2a
Details
@github-actions
jemalloc
Details
@github-actions
valgrind
Details
@github-actions
coroutine=ucontext
Details
@github-actions
coroutine=pthread
Details
@github-actions
disable-jit-support
Details
@github-actions
disable-dln
Details
@github-actions
disable-rubygems
Details
@github-actions
OPT_THREADED_CODE=1
Details
@github-actions
OPT_THREADED_CODE=2
Details
@github-actions
OPT_THREADED_CODE=3
Details
@github-actions
NDEBUG
Details
@github-actions
RUBY_DEBUG
Details
@github-actions
USE_EMBED_CI=0
Details
@github-actions
USE_FLONUM=0
Details
@github-actions
USE_LAZY_LOAD
Details
@github-actions
DEBUG_FIND_TIME_NUMGUESS
Details
@github-actions
DEBUG_INTEGER_PACK
Details
@github-actions
GC_DEBUG_STRESS_TO_CLASS
Details
@github-actions
MJIT_FORCE_ENABLE
Details
@github-code-scanning
CodeQL No new or fixed alerts
Details
@travis-ci
Travis CI - Pull Request Build Passed
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
@marcandre
Copy link
Member

@marcandre marcandre commented Aug 6, 2021

Thank you @jeremyevans <3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants