rubyguides

Float

Float.new, Float()

The Float class represents floating-point numbers in Ruby, following the IEEE 754 double-precision format. Floats are used when you need decimal numbers with fractional parts.

Creating Floats

# Direct assignment
x = 3.14159
y = -2.5
z = 1.0

# Using Float() conversion
Float(42)      # => 42.0
Float("3.14")  # => 3.14

# From integers
100.to_f       # => 100.0

# Scientific notation
1e5            # => 100000.0
1.5e-3        # => 0.0015

Each creation form produces the same Float instance, so you can pick the notation that reads best in context. Scientific notation is especially handy for very large or very small values where counting zeros would be error-prone in both directions.

Float Methods

# Infinite and NaN checks
(1.0 / 0).infinite?  # => 1 (positive infinity)
(-1.0 / 0).infinite? # => -1 (negative infinity)
(0.0 / 0).nan?       # => true (Not a Number)

# Rounding
3.14159.round(2)    # => 3.14
3.14159.floor       # => 3
3.14159.ceil        # => 4

# Conversion
3.14159.to_i        # => 3 (truncates)
3.14159.to_s        # => "3.14159"

Methods like round, floor, and ceil give you control over display precision separately from the internal value. The nan? and infinite? checks are essential guards when floats come from division or external input, where nonsensical results can appear without raising exceptions or crashing the program.

Precision Considerations

# Floating-point precision issues
0.1 + 0.2  # => 0.30000000000000004

# Use BigDecimal for precision
require 'bigdecimal'
BigDecimal("0.1") + BigDecimal("0.2")
# => 0.3 (exact)

# Comparing floats
a = 0.1 + 0.2
b = 0.3
(a - b).abs < 0.0001  # => true (tolerance comparison)

Float equality checks should always use a tolerance rather than ==, because the binary representation of decimal fractions introduces tiny rounding differences. The tolerance approach keeps tests and comparisons reliable without switching to BigDecimal for every single calculation you perform in your code.

Practical Examples

Mathematical Operations

# Basic math
2.5 + 1.5    # => 4.0
3.0 * 4.0    # => 12.0
10.0 / 3.0   # => 3.3333333333333335
5.0 ** 2     # => 25.0

# Using Math module
Math.sqrt(16.0)   # => 4.0
Math.sin(Math::PI / 2)  # => 1.0
Math.log(Math::E)       # => 1.0

The Math module functions expect and return Float values, making them a natural companion for scientific and engineering calculations. For most everyday math, the basic arithmetic operators are all you need to get the right answer quickly and without extra imports.

Working with Currency (use BigDecimal in production)

# Simple price calculations (warning: precision issues!)
price = 19.99
tax = price * 0.08
total = price + tax
# => 21.5892

# Rounding for display
puts "Total: $#{total.round(2)}"  # => Total: $21.59

Currency calculations with floats produce rounding noise that can add up over many transactions in a busy system. Rounding for display is fine, but storing or accumulating money values as floats will eventually cause cent-level discrepancies that are hard to track down after the fact.

Temperature Conversion

def celsius_to_fahrenheit(c)
  c * 9.0 / 5 + 32
end

def fahrenheit_to_celsius(f)
  (f - 32) * 5.0 / 9
end

celsius_to_fahrenheit(100)    # => 212.0
fahrenheit_to_celsius(32)      # => 0.0

Temperature formulas are a good fit for floats because the inputs and outputs are inherently approximate values rather than exact numbers. The small rounding errors from float arithmetic are far smaller than any real-world measurement precision a thermometer could provide in practice.

Division Behavior

# Integer vs float division
5 / 2       # => 2 (integer division)
5.0 / 2     # => 2.5
5 / 2.0     # => 2.5
5.0 / 2.0   # => 2.5

Ruby’s division behavior depends on the operand types: integer division truncates toward zero, but including at least one float operand produces a float result. Adding .0 to one of the values is the quickest way to switch from integer to float division.

Working with floating point values

Floats are easy to use, but they are not exact decimal storage. That matters most when the numbers represent money, measurements, or any value that must round cleanly for display or comparison. A small tolerance is often better than checking for exact equality, and BigDecimal can be a better match when the math must stay precise. Even then, floats are still useful for quick calculations, scientific work, and code where a little rounding noise is acceptable. The important part is knowing when the numbers are approximate.

In day-to-day code, the safest pattern is to keep float math small and intentional. Round when you present a value, compare with a tolerance when you need equality, and avoid assuming that a decimal literal always has an exact binary form. That habit keeps surprises down in calculations that look simple on the surface. When precision really matters, switch to a type that was designed for exact decimal work instead of trying to force floats into that role.

Floats also make a lot of sense for values that are inherently approximate, such as angles, sensor readings, and display math. In those cases the goal is not exact decimal storage but a stable, usable result. If you frame the problem that way, the limitations of float arithmetic become much easier to manage.

That framing is also helpful when you decide what to display to a user. The internal value can stay approximate while the presentation rounds to the number of digits that actually matter. Keeping those two concerns separate makes float-heavy code easier to trust, especially when the math is only one small part of the feature.

Special Values

# Infinity
Float::INFINITY     # => Infinity
1.0 / 0             # => Infinity
Float::INFINITY > Float::INFINITY  # => false

# Negative infinity
-1.0 / 0            # => -Infinity

# Not a Number (NaN)
0.0 / 0             # => NaN
Math.sqrt(-1)       # => NaN

Floats are essential for scientific computing, graphics, and any application requiring decimal math, but be aware of their precision limitations.

See Also