2

Possible Duplicate:
Arithmetic in ruby

The status_update model takes 2 values in, does some simple calculations with them, and assigns 'current_lbm' and 'current_bf_pct' from there.

current_lbm and current_bf_pct will produce massive decimals if I don't restrain them so I used the .round(2) method to limit the values to 2 decimal places.

Here is the method that does this.

after_initialize :default_values
.
.
def default_values      
 if self.current_bf_pct >= 0.5
   self.current_bf_pct /= 100
    if self.current_bf_pct <= 0.04
      self.current_fb_pct *= 100
    end 
 end
 self.current_fat_weight = self.current_weight * self.current_bf_pct
 self.current_lbm = self.current_weight - self.current_fat_weight
 self.current_fat_weight = self.current_fat_weight.round(2)
 self.current_lbm = self.current_lbm.round(2)
end   

Here are the results:

09/13/2012 186.0 4.5 177.63 8.37
09/13/2012 187.0 5.5 176.72 10.29
09/13/2012 188.0 6.5 175.78 12.22
09/13/2012 189.0 7.5 174.83 14.18
09/13/2012 190.0 8.5 173.85 16.15
09/13/2012 191.0 9.5 172.86 18.15
09/13/2012 192.0 10.5 171.84 20.16
09/13/2012 193.0 11.5 170.81 22.2
09/13/2012 194.0 12.5 169.75 24.25
09/13/2012 195.0 13.5 168.68 26.33
09/13/2012 196.0 14.499999999999998 167.58 28.42
09/13/2012 197.0 15.5 166.47 30.54
09/13/2012 198.0 16.5 165.33 32.67
09/13/2012 199.0 17.5 164.18 34.82
09/13/2012 200.0 18.5 163.0 37.0   

my question is... what the heck is up with 14.499999999999998??

These are the results from the view. The current_bf_pct row is the 3rd one from the dates. They aren't decimals because I multiply them by 100 in the view.

Community
  • 1
  • 1
Nick Res
  • 2,154
  • 5
  • 30
  • 48
  • What is your puts/print statement or view code? I'm not sure what the 14.499999999 is, since you don't say what the second one from the dates are. – Marlin Pierce Sep 13 '12 at 20:30

1 Answers1

3

You can't avoid this if you're using displaying floats as-is (see Arithmetic in ruby). I suggest you convert your floats to strings for display.

Example (your actual result may vary):

>> 7.3-7.2
=> 0.09999999999999964

Convert to string with 1 decimal place:

>> '%.1f' % (7.3-7.2)
=> "0.1"

The '%' operator is shorthand for:

sprintf '%.1f', (7.3-7.2)

Read up on sprintf. It's a bit of a learning curve but it's very powerful.

Another solution is to use BigDecimal (the 2nd argument is the precision - make sure you understand what this means):

BigDecimal(7.3-7.2, 1).to_s

If you use a large enough precision, you'll see the problem again:

>> BigDecimal(7.3-7.2, 16).to_s
=> "0.09999999999999964"
Community
  • 1
  • 1
Kelvin
  • 20,119
  • 3
  • 60
  • 68
  • 1
    Yes, if current_bf_pct is the one with the 14.4999999, it's because you never round it. You should round when you display, not round and save to a variable. – Marlin Pierce Sep 13 '12 at 20:36
  • The BigDecimal method worked nicely. As mentioned, I placed the edited number in the view instead of in the model. You guys rock! – Nick Res Sep 13 '12 at 21:19