Maybe a Ruby question: Strange math!

irb(main):004:0> (19.9 * 100).to_i => 1989 irb(main):005:0> (19.9 * 100) => 1990.0 irb(main):006:0> 1990.0.to_i => 1990

Can someone explain this? Regards Till Vollmer

Floating point number aren’t completely accurate.

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

crazy stuff indeed.

I understand (vaguely) the issue with FP numbers not being accurate, but I can't wrap my head around this.

I can't seem to find any real discussion of ways to deal with this. Is the only workable solution to this issue to work exclusively with Integers?

Eric

etlund wrote:

crazy stuff indeed.

I understand (vaguely) the issue with FP numbers not being accurate, but I can't wrap my head around this.

I can't seem to find any real discussion of ways to deal with this. Is the only workable solution to this issue to work exclusively with Integers?

Eric

Floating point numbers can only approximate some integers. In your case, the final product of 19.9 * 100 is probably something like

1989.99999999999999999999998, which just displays as 1990.0 in most cases.

Now, .to_i truncates off the decimal part pretty ruthlessly.

To be safe, you should probably use a function like .round instead of .to_i unless you are absolutely certain you can do that safely.

.round will round the number to the nearest integer, which is really what you want.

_Kevin

Yup. It's standard to deal with integers. If you look at the banking system then everything there is in whole numbers. On the computer level $55 is always represented as 5500. However that method may not work for your needs.

BigDecimal seems to do a bunch. Never used it thought.

001:0> require 'bigdecimal' 002:0> require 'bigdecimal/util' 003:0> (19.9.to_d * 100).to_i => 1990

http://www.ruby-doc.org/stdlib/libdoc/bigdecimal/rdoc/index.html

irb(main):004:0> (19.9 * 100).to_i => 1989 irb(main):005:0> (19.9 * 100) => 1990.0 irb(main):006:0> 1990.0.to_i => 1990

Can someone explain this?

to_i truncates, so

irb(main):001:0> 99.9.to_i => 99

You are probably expecting rounding rather than truncation:

irb(main):002:0> 99.9.round => 100

Cheers, Bob