From: nobu@... Date: 2018-01-18T04:05:26+00:00 Subject: [ruby-core:84912] [Ruby trunk Feature#14362] use BigDecimal instead of Float by default Issue #14362 has been updated by nobu (Nobuyoshi Nakada). You can write "exact" number by `1.2r`. ---------------------------------------- Feature #14362: use BigDecimal instead of Float by default https://bugs.ruby-lang.org/issues/14362#change-69620 * 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: