6 ms·
Great article. Just one small tip: instead of using the BigDecimal("123.45") notation, I much prefer typing 123.45.to_d. Anywhere you used Floats, you can just
by pqdbr 6y ago
Great article. Just one small tip: instead of using the BigDecimal("123.45") notation, I much prefer typing 123.45.to_d.
Anywhere you used Floats, you can just replace them with BigDecimals. They work just the same. Some people get scared by them because they are always printed in scientific notation in the console, but you can just call `.to_s` on them to see them in a regular format:
123.45.to_d
=> 0.12345e3
123.45.to_s
=> "123.45"
So don't get worried about the display. The behave exactly the same as a float, you can sum, multiply, and so on, and then you call .to_s when it's time to display it.
Also any BigDecimal#round will give you an integer (just like .to_i will), but you can also call Bigdecimal#round(2) to round to, for instance, 2 decimal places.
Also, if you are coding anything related to currencies, I strongly suggest you always use integers to store the amounts in cents. And when you need to divide it for calculations, just call `.to_d`, do your math, and then `.round` at the end, so you discard the fractions of cents. It works wonders, and the math will add up just like in Excel :)
- edflsafoiewq 6y agoBigDecimal("123.45") != 123.45.to_d. You should always prefer the former. In the latter, 123.45 is first read as a float, which introduces an error because it is not exactly representable as a float.
- pqdbr 6y agoRuby 2.7.2, just fire up irb: BigDecimal("123.45") == 123.45.to_d => true
- edflsafoiewq 6y agoShows you what I know. I thought I had tested this. I guess it keeps only a certain amount of precision.
- gioele 6y agoThat is just a coincidence (decimal ending in "5"), plus the fact that `.to_d` does some cleanup preprocessing. Counterexample: BigDecimal("1.5999999999999996") == 1.5999999999999996.to_d => false The most ergonomic way to initialize decimal numbers is IMO "123.45".to_d (Note the quotes around the number. `.to_d` is being called on a string.) BigDecimal's only lossless API is through strings. It would be nice to have native support for decimals at the parser level: 0d123.45 => BigDecimal("123.45")