From: mail@... Date: 2018-01-30T10:46:31+00:00 Subject: [ruby-core:85253] [Ruby trunk Feature#14362] use BigDecimal instead of Float by default Issue #14362 has been updated by sos4nt (Stefan Sch����ler). nobu (Nobuyoshi Nakada) wrote: > Rational and BigDecimal do not cover irrational numbers. That's exactly what I wanted to say. Changing Float to BigDecimal only solves _some_ problems. It's not a magic bullet. (neither is Rational) BigDecimal's documentation blames Float for introducing subtle errors, but it has its own issues, even for numbers with a finite decimal representation: ```ruby n = 2 ** 128 #=> 340282366920938463463374607431768211456 (BigDecimal(1) / n) * n #=> # ``` That's neither _"very accurate"_ nor does it qualify as _"correct answers people expect"_. In order to get the correct result, I have to resort to [`BigDecimal#div`](http://ruby-doc.org/stdlib-2.5.0/libdoc/bigdecimal/rdoc/BigDecimal.html#method-i-div) and provide the number of significant digits manually: ```ruby BigDecimal(1).div(n, 91) * n #=> # ``` ---------------------------------------- Feature #14362: use BigDecimal instead of Float by default https://bugs.ruby-lang.org/issues/14362#change-70011 * Author: AaronLasseigne (Aaron Lasseigne) * Status: Open * Priority: Normal * Assignee: * Target version: ---------------------------------------- When writing a decimal the default type assigned is `Float`: ```ruby > 1.2.class => Float ``` This is great for memory savings and for application speed but it comes with accuracy issues: ```ruby > 129.95 * 100 => 12994.999999999998 ``` Ruby's own `BigDecimal` docs say: > Decimal arithmetic is also useful for general calculation, because it provides the correct answers people expect���whereas normal binary floating point arithmetic often introduces subtle errors because of the conversion between base 10 and base 2. What if `BigDecimal` was moved into the Ruby core and made the default for numbers like `1.2`? ```ruby > 1.2.class => BigDecimal ``` I realize this goes against the 3x3 goal but I think `BigDecimal` is preferable over `Float` for developer happiness. I've seen lots of developers stumble when first learning about the pitfalls of `Float`. I've see test suites where a range is tested for because of answers like `12994.999999999998` instead of `12995.0`. At one point trading accuracy for performance made sense. I'm not sure that's still the case today. Right now a decimal generates the faster and less accurate `Float`. Developers have to opt-in to the slower but safer `BigDecimal` by manually requesting a `BigDecimal`. By flipping this we default to the safer version and ask developers to opt-in to the faster but less accurate `Float` if needed. ```ruby > 1.2.class => Decimal > Float.new('1.2') => 1.2 ``` There could also be a shorthand for float where the number is followed by an `f` (similar to Rational). ```ruby 1.2f # => Float ``` The change would help "provide the correct answers people expect". The change would be mostly seamless from an interface standpoint. The only methods on `Float` and not on `BigDecimal` appear to be `rationalize`, `next_float`, and `prev_float`. I suspect those methods are rarely used. The increased accuracy seems unlikely to cause code issues for people. The two largest downsides that I can come up with are speed and display. I'm not sure what kind of hit is taken by handling all decimals as `BigDecimal`. Would an average Rails application see a large hit? Additionally, the display value of `BigDecimal` is engineering notation. This is also the default produced by `to_s`. It's harder to read and might mess up code by displaying things like "0.125e2" instead of "12.5". Certainly the default produced by `to_s` could change to the conventional floating point notation. A change this significant would likely target Ruby 3 so there would be time to make some changes like adding a `BigDecimal#rationalize` method or changing the default output of `BigDecimal#to_s`. Thank you for considering this. -- https://bugs.ruby-lang.org/ Unsubscribe: