Floating-Point Precision in Ruby: Why 0.1 + 0.33 ≠ 0.43
Ruby's 0.1 + 0.33 does not equal 0.43 because of binary floating-point rounding, and Rational, BigDecimal, and tolerance comparisons each fix it differently.
· 1 min read
0.1 + 0.33 == 0.43 returns false in Ruby. Not a bug: it’s what IEEE 754 floating-point does to decimal fractions that don’t have exact binary representations.
sum = 0.1 + 0.33
puts sum == 0.43 # false
Why the binary representation breaks
Floating-point numbers store real numbers in binary, as defined by IEEE 754. Most decimal fractions don’t map onto binary exactly, the same way 1/3 has no exact decimal representation. 0.1 in binary is 0.00011001100110011..., an infinitely repeating pattern that gets truncated to fit the available bits. Add two truncated approximations together and the rounding error shows up in the result.
This matters most where an exact decimal answer is the requirement: money, quantities, anything that gets compared with == downstream.
Three ways around it
Rational numbers
require 'rational'
rational_sum = Rational(1, 10) + Rational(33, 100)
puts rational_sum # (43/100)
puts rational_sum.to_f # 0.43
Rational stores the fraction exactly, no binary approximation involved.
BigDecimal for money
require 'bigdecimal'
big_decimal_sum = BigDecimal("0.1") + BigDecimal("0.33")
puts big_decimal_sum # 0.43
BigDecimal is the standard choice for financial arithmetic, where accumulated rounding error is not acceptable.
Tolerance comparison
tolerance = 0.0001
puts (sum - 0.43).abs <= tolerance # true
If you’re stuck with floats, compare within a tolerance instead of with ==.
The principle
Floating point is fine for most calculations and wrong for exact decimal ones. If the answer needs to be exactly 0.43 and not 0.43000000000000004, that’s a sign to reach for Rational or BigDecimal, not to add more decimal places and hope.