Ruby BigDecimal#new: How to Create BigDecimal Values
There are several ways to create BigDecimal values in Ruby, and the approach you choose matters. The most important rule applies to all of them: always use strings as the source value, not floats. We will cover why shortly.
The BigDecimal() Kernel Method
require 'bigdecimal'
BigDecimal("1.23") # => 0.123e1
BigDecimal("0.0825") # => 0.825e-1
BigDecimal("1000") # => 0.1e4
BigDecimal("0") # => 0.0
This is the canonical way to create BigDecimal values. The string is parsed exactly as written, with no binary floating-point involvement. The output format looks unfamiliar at first — BigDecimal uses engineering notation internally — but the value is exact.
Do Not Pass a Float
Passing a float literal to BigDecimal() captures the float’s binary imprecision rather than the decimal value you intended:
# Wrong: inherits floating-point error
BigDecimal(0.1)
# => 0.1000000000000000055511151231257827021181583404541015625e0
# Correct: parse from string
BigDecimal("0.1")
# => 0.1e0
That enormous decimal expansion is the actual binary float value that your CPU stores. When you pass a string instead, BigDecimal parses your decimal intent directly. This single distinction is worth remembering, because floating-point-derived BigDecimals can silently produce wrong financial calculations.
The bigdecimal/util Helper
Requiring bigdecimal/util adds to_d to String, Integer, Float, and Rational, which often leads to more readable code:
require 'bigdecimal'
require 'bigdecimal/util'
"1.23".to_d # => 0.123e1
123.to_d # => 0.123e3
(1/3r).to_d(10) # => 0.3333333333e0 (10 significant digits)
Float#to_d converts via the float’s string representation, which avoids the binary precision issue:
0.1.to_d # => 0.1e0
This is one of the few times it is safe to start from a float — to_d goes through the string representation rather than capturing the raw binary value.
Creating from Integer
require 'bigdecimal'
BigDecimal(42) # => 0.42e2
42.to_d # works with bigdecimal/util
Integers are exact in Ruby, so creating a BigDecimal from one is always safe. No precision is lost in the conversion.
Creating from Rational
require 'bigdecimal'
require 'bigdecimal/util'
(1/3r).to_d(15)
# => 0.333333333333333e0
The second argument to to_d sets the number of significant digits for the conversion. For repeating fractions like one-third, you must supply a digit count — otherwise BigDecimal has no way to know where to stop.
Special Values
require 'bigdecimal'
BigDecimal::INFINITY # => Infinity
-BigDecimal::INFINITY # => -Infinity
BigDecimal::NAN # => NaN
These constants let you check for edge cases:
n = BigDecimal("1.0") / BigDecimal("0")
n.infinite? # => 1
n.nan? # => false
Division by zero produces Infinity rather than raising an exception, which differs from Integer division behavior. If your code divides BigDecimal values where the denominator might be zero, it is worth checking with infinite? or nan? before using the result.