HoodieOnRails
HoodieOnRails

Reputation: 248

Rails: Math not computing correctly. It's off by .00000000000001

My rails app is not doing math correctly. I think this has something to do with the variable types (int vs float) but not sure what's wrong.

The root problem is this method in my Stat model:

def lean_mass
 self.weight * 0.01 * (100 - self.body_fat)
end

Where

Stat.weight = 140
Stat.body_fat = 15

it returns 119.00000000000001 instead of 119.

However, where

Stat.weight = 210
Stat.body_fat = 15

it returns 178.5, the correct number.

Anyone know why it's throwing in that small decimal?

The datatype for weight is integer and body_fat is decimal if that helps.

Upvotes: 4

Views: 365

Answers (2)

spickermann
spickermann

Reputation: 106982

Floating-point numbers cannot precisely represent all real numbers. And furthermore floating-point operations cannot precisely represent every arithmetic operation. This leads to many surprising situations.

A simple example that shows this behavior:

0.1 + 0.2
#=> 0.30000000000000004

I advise to read: https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

You can avoid most of this problems by using BigDecimal instead of floats:

require 'bigdecimal'
BigDecimal.new('0.01') * 140 * (100 - 15)
#=> 119.0

Upvotes: 14

Boris Brodski
Boris Brodski

Reputation: 8715

Take a look at ruby BigDecimal

For example, try:

sum = 0
10_000.times do
  sum = sum + 0.0001
end
print sum #=> 0.9999999999999062

and contrast with the output from:

require 'bigdecimal'

sum = BigDecimal.new("0")
10_000.times do
  sum = sum + BigDecimal.new("0.0001")
end
print sum #=> 0.1E1

Upvotes: 3

Related Questions