# Bug in converting float to int?

**URL:** <https://www.ruby-forum.com/t/bug-in-converting-float-to-int/160223>\
**Category:** Ruby\
**Created:** [February 13, 2009, 6:43am UTC](https://www.ruby-forum.com/t/bug-in-converting-float-to-int/160223 "2009-02-13T06:43:09Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![renian](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/87869e/32.png) [@renian](https://www.ruby-forum.com/u/renian)\
**Post date:** [February 13, 2009, 6:43am UTC](https://www.ruby-forum.com/t/bug-in-converting-float-to-int/160223/1 "2009-02-13T06:43:09Z")

</div>

I just tried this on 1.8.6. Is this a bug or am I missing something?

> > a=10.12  
> > =\> 10.12
> 
> > (a\*100).to\_i  
> > =\> 1011

And if this is in fact intended behavior, how can I actually get the  
results I want? (Converting dollars and cents into cents)

---

<div class="post-metadata">

**Author:** ![renian](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/87869e/32.png) [@renian](https://www.ruby-forum.com/u/renian)\
**Post date:** [February 13, 2009, 6:53am UTC](https://www.ruby-forum.com/t/bug-in-converting-float-to-int/160223/2 "2009-02-13T06:53:07Z")

</div>

Oh and it looks like this only happens with floats ending in .12.

Ruby thinks 12 hundredths is not as big as it’s buddies?? 🙂

---

<div class="post-metadata">

**Author:** ![renian](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/87869e/32.png) [@renian](https://www.ruby-forum.com/u/renian)\
**Post date:** [February 13, 2009, 6:58am UTC](https://www.ruby-forum.com/t/bug-in-converting-float-to-int/160223/3 "2009-02-13T06:58:19Z")

</div>

Jeff V. wrote:

> I just tried this on 1.8.6. Is this a bug or am I missing something?
> 
> > > a=10.12  
> > > =\> 10.12  
> > > (a\*100).to\_i  
> > > =\> 1011
> 
> And if this is in fact intended behavior, how can I actually get the  
> results I want? (Converting dollars and cents into cents)

A FAQ.

irb(main):001:0\> sprintf(“%.16f”, 100\*10.12)  
=\> “1011.9999999999998863”

> **[Floating-point arithmetic | Accuracy problems](https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems)**
>
> The fact that floating-point numbers cannot accurately represent all real numbers, and that floating-point operations cannot accurately represent true arithmetic operations, leads to many surprising situations. This is related to the finite precision with which computers generally represent numbers.
> For example, the decimal numbers 0.1 and 0.01 cannot be represented exactly as binary floating-point numbers. In the IEEE 754 binary32 format with its 24-bit significand, the result of attempting to ...

---

<div class="post-metadata">

**Author:** ![renian](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/87869e/32.png) [@renian](https://www.ruby-forum.com/u/renian)\
**Post date:** [February 13, 2009, 7:08am UTC](https://www.ruby-forum.com/t/bug-in-converting-float-to-int/160223/4 "2009-02-13T07:08:56Z")

</div>

On Feb 13, 2009, at 12:41 AM, Jeff V. wrote:

> I just tried this on 1.8.6. Is this a bug or am I missing something?
> 
> > > a=10.12  
> > > =\> 10.12
> > 
> > > (a\*100).to\_i  
> > > =\> 1011

Ruby floating point values are stored in binary format.  
10.12 (decimal) can not be represented exactly in binary:

> > sprintf("%0.50f", 10.12)  
> > =\> “10.11999999999999921840299066388979554176330566406250”

The default conversion of float to string (e.g., for output) rounds  
to 6 (or maybe 7) places and truncates trailing zeros:

> > sprintf("%0.6f", a).sub(/0+\Z/,’’)  
> > =\> “10.12”

Float#to\_i truncates:

> > sprintf("%0.50f", 10.12 \* 100 )  
> > =\> “1011.99999999999988631316227838397026062011718750000000”
> 
> > (10.12 \* 100).to\_i  
> > =\> 1011

---

<div class="post-metadata">

**Author:** ![renian](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/87869e/32.png) [@renian](https://www.ruby-forum.com/u/renian)\
**Post date:** [February 13, 2009, 7:06pm UTC](https://www.ruby-forum.com/t/bug-in-converting-float-to-int/160223/5 "2009-02-13T19:06:39Z")

</div>

Gary W. wrote:

> Ruby floating point values are stored in binary format.  
> 10.12 (decimal) can not be represented exactly in binary:
> 
> > > sprintf("%0.50f", 10.12)  
> > > =\> “10.11999999999999921840299066388979554176330566406250”

Clifford H. wrote:

> Avoid using floating point. Seriously. Some might advice you to round:  
> (a\*100).round =\> 1012, but that’s _unreliable_, even with some quite  
> small number of digits.
> 
> Store cents as an integer, or use BigDecimal.

Thanks everyone, quite interesting info there. It looks like I will be  
doing my dollars to cents math a little differently.

Clifford, can you elaborate on why round is unreliable?

---

<div class="post-metadata">

**Author:** ![renian](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/87869e/32.png) [@renian](https://www.ruby-forum.com/u/renian)\
**Post date:** [February 13, 2009, 9:02pm UTC](https://www.ruby-forum.com/t/bug-in-converting-float-to-int/160223/6 "2009-02-13T21:02:08Z")

</div>

Jeff V. wrote:

> I just tried this on 1.8.6. Is this a bug or am I missing something?
> 
> > > a=10.12  
> > > =\> 10.12
> > 
> > > (a\*100).to\_i  
> > > =\> 1011
> 
> And if this is in fact intended behavior, how can I actually get the  
> results I want? (Converting dollars and cents into cents)

Just to tack on my 1.9997438 cents 😉

We had a big go-round about this a while back. This behavior is not  
specific to Ruby. The reason Ruby behaves like this is that it adheres  
to the IEEE standard for floating point numbers, which is common to most  
programming languages. A standard so old that it was first pressed into  
clay tablets back when computers were powered by oxen and water wheels.  
Ruby keeps this standard because it’s fast and it reflects the way that  
computers really work with numbers. There are plenty of alternatives for  
dealing with floating point numbers which are usually offered as high  
precision scientific numerical packages. But these are almost always  
slower than the IEEE standard. And, while they are less lousy (I imagine  
most could keep two decimal places straight) they are still prone to  
precision error, just because computers are, at their very core, integer  
only.

---

<div class="post-metadata">

**Author:** ![renian](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/87869e/32.png) [@renian](https://www.ruby-forum.com/u/renian)\
**Post date:** [February 13, 2009, 9:47pm UTC](https://www.ruby-forum.com/t/bug-in-converting-float-to-int/160223/7 "2009-02-13T21:47:59Z")

</div>

Raphael C. wrote:

> Just to tack on my 1.9997438 cents 😉
> 
> We had a big go-round about this a while back. This behavior is not  
> specific to Ruby. The reason Ruby behaves like this is that it adheres  
> to the IEEE standard for floating point numbers, which is common to most  
> programming languages. A standard so old that it was first pressed into  
> clay tablets back when computers were powered by oxen and water wheels.  
> Ruby keeps this standard because it’s fast and it reflects the way that  
> computers really work with numbers. There are plenty of alternatives for  
> dealing with floating point numbers which are usually offered as high  
> precision scientific numerical packages. But these are almost always  
> slower than the IEEE standard. And, while they are less lousy (I imagine  
> most could keep two decimal places straight) they are still prone to  
> precision error, just because computers are, at their very core, integer  
> only.

Just for “fun”, I tried the following on g++ 4.01 (PPC version)

#include

using namespace std;

int main(int argc, char\* argv[]) {  
float x = 10.12;  
int y = (int) (x \* 100.0);  
cout \<\< x \<\< " , " \<\< y \<\< endl;  
return(0);  
}

which generates the familiar output…

10.12 , 1011

---

<div class="post-metadata">

**Author:** ![renian](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/87869e/32.png) [@renian](https://www.ruby-forum.com/u/renian)\
**Post date:** [February 13, 2009, 7:25am UTC](https://www.ruby-forum.com/t/bug-in-converting-float-to-int/160223/8 "2009-02-13T07:25:56Z")

</div>

Jeff V. wrote:

> I just tried this on 1.8.6. Is this a bug or am I missing something?

Wikipedia is good, but I think the best-known article on this is here:  
[http://docs.sun.com/source/806-3568/ncg\_goldberg.html](http://docs.sun.com/source/806-3568/ncg_goldberg.html), entitled  
“What Every Scientist Should Know About Floating-Point Arithmetic”.

> And if this is in fact intended behavior, how can I actually get the  
> results I want? (Converting dollars and cents into cents)

Avoid using floating point. Seriously. Some might advice you to round:  
(a\*100).round =\> 1012, but that’s _unreliable_, even with some quite  
small number of digits.

Store cents as an integer, or use BigDecimal.

Clifford H…

---

<div class="post-metadata">

**Author:** ![renian](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/87869e/32.png) [@renian](https://www.ruby-forum.com/u/renian)\
**Post date:** [February 14, 2009, 12:36am UTC](https://www.ruby-forum.com/t/bug-in-converting-float-to-int/160223/9 "2009-02-14T00:36:20Z")

</div>

Jeff V. wrote:

> Clifford, can you elaborate on why round is unreliable?

If you’ve read the Goldberg paper, I doubt I can add anything.

Conversions to/from ASCII are never totally symmetrical.  
You can convert to float and back to string and get a  
different result, for the simple reason that it’s not an  
exact one-to-one mapping. For _some_ of those patterns,  
the change in the last digit will be _propagated_ by the  
rounding process, resulting in a change to your value.

I recall learning this in 1986 on an HP500. which converted  
516.12 to double and back as 516.11 - only five significant  
figures.

Clifford H…
