# Using Float For Currency

**URL:** <https://www.ruby-forum.com/t/using-float-for-currency/50102>\
**Category:** Ruby\
**Created:** [December 13, 2005, 1:05am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102 "2005-12-13T01:05:30Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 1:05am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/1 "2005-12-13T01:05:30Z")

</div>

Howdy,

I have some methods that manipulate floats that represent a currency  
amount.

I often end up with more precision than I need, i.e.: $9.756.

What is the best way to scale that to 9.76?

Cheers.

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 1:14am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/2 "2005-12-13T01:14:33Z")

</div>

Quoting Hunter’s Lists [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Howdy,
> 
> I have some methods that manipulate floats that represent a  
> currency amount.
> 
> I often end up with more precision than I need, i.e.: $9.756.
> 
> What is the best way to scale that to 9.76?

If you’re doing anything that matters, don’t use floats for  
currency. There are a lot of really nasty subtle issues that will  
lose money between the cracks.

Usually you want a specialized currency type which uses  
fixed-precision arithmetic.

-mental

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 1:23am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/3 "2005-12-13T01:23:35Z")

</div>

Thanks. Fortunately this is just some quick guestimation throw-away  
stuff.

No real need for precision. I will take a look at BigDecimal but in the  
meantime, any thoughts on the original question?

Thx

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 1:15am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/4 "2005-12-13T01:15:57Z")

</div>

unknown wrote:

> Quoting Hunter’s Lists [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> 
> > Howdy,
> > 
> > I have some methods that manipulate floats that represent a  
> > currency amount.
> > 
> > I often end up with more precision than I need, i.e.: $9.756.
> > 
> > What is the best way to scale that to 9.76?
> 
> If you’re doing anything that matters, don’t use floats for  
> currency. There are a lot of really nasty subtle issues that will  
> lose money between the cracks.
> 
> Usually you want a specialized currency type which uses  
> fixed-precision arithmetic.

BigDecimal is good.

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 1:23am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/5 "2005-12-13T01:23:36Z")

</div>

On 12/12/05, Hunter’s Lists [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Howdy,
> 
> I have some methods that manipulate floats that represent a currency amount.
> 
> I often end up with more precision than I need, i.e.: $9.756.
> 
> What is the best way to scale that to 9.76?

Try:  
val = 9.756  
sprintf(“%.2f”, val)  
That says "print ‘val’ as a floating point value, with two decimal  
places of precision.

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 5:54am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/6 "2005-12-13T05:54:13Z")

</div>

“Wilson B.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> val = 9.756  
> sprintf(“%.2f”, val)  
> That says "print ‘val’ as a floating point value, with two decimal  
> places of precision.

Or just  
“%.2f” % val

Cheers,  
Dave

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 6:12am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/7 "2005-12-13T06:12:15Z")

</div>

On 12/12/05, removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> If you’re doing anything that matters, don’t use floats for  
> currency. There are a lot of really nasty subtle issues that will  
> lose money between the cracks.
> 
> Usually you want a specialized currency type which uses  
> fixed-precision arithmetic.

What cracks can I lose money through?

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 2:38am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/8 "2005-12-13T02:38:47Z")

</div>

Hunter’s Lists wrote:

> Howdy,
> 
> I have some methods that manipulate floats that represent a currency amount.
> 
> I often end up with more precision than I need, i.e.: $9.756.
> 
> What is the best way to scale that to 9.76?

require ‘bigdecimal’

amount = BigDecimal.new(‘9.756’)  
rounded = (amount \* 100).round / 100  
printf(’%.02f’, rounded)

## Outputs ‘9.76’

Neil S. - removed\_email\_address@domain.invalid

‘A republic, if you can keep it.’ – Benjamin Franklin

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 4:02pm UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/9 "2005-12-13T16:02:04Z")

</div>

On Tue, 13 Dec 2005, Neil S. wrote:

> amount = BigDecimal.new(‘9.756’)  
> rounded = (amount \* 100).round / 100  
> printf(’%.02f’, rounded)
> 
> Outputs ‘9.76’

There is at least one point more to make about rounding: this method has  
a  
bias when floats ending with a 5 are involved. In the extreme case, when  
all you three-decimal currency amounts end in a 5 (like $9.755, $9.765)  
then all are rounded upwards. Instead, half of them should be rounded  
up,  
the other half down. A good method to do that is to round to the  
nearest even digit:

$9.755 -\> $9.76  
$9.765 -\> $9.76 (not $9.77)

The attached method round2 does this (although probably not very  
efficiently):  
8.5.round2 -\> 8  
9.765.round2(0.01) -\> 9.76

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 8:06am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/10 "2005-12-13T08:06:29Z")

</div>

Joe Van D. wrote:

> What cracks can I lose money through?

Floating point numbers represent an extremely wide range of values -  
much wider than their integer counterparts. This is handled through an  
exponent and mantissa. For this ability, they trade off precision.

Think about the case of adding a large floating point number to a small  
floating point number:

```
 irb(main):001:0> a = 1.0e30
 => 1.0e+030
 irb(main):002:0> b = 1.0e-30
 => 1.0e-030
 irb(main):003:0> a + b
 => 1.0e+030

```

While this is an extreme example, it does demonstrate the loss of  
precision. Essentially, in floating point arithmetic we’re trying to  
squeeze much more out of, say 32 or 48 or 64 bits.

Integer arithmetic, on the other hand, is exact. And therefore so is  
fixed point arithmetic; however, fixed point doesn’t enjoy the wide  
representation range as floats.

The bottom line is you should never use floating point when it comes to  
money. Eventually you’re going to miss pennies. Instead represent  
things in the smallest denomination, such as cents, and fix it up in  
presentation, or use a custom Money column type, or data type.

There’s your cracks! Just say no… unless you’re a hot chick. Even  
then it’s questionable.

–Steve

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 11:35pm UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/11 "2005-12-13T23:35:10Z")

</div>

Quoting Malte M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Joe Van D.:
> 
> > What cracks can I lose money through?
> 
> irb\> 0.2 - 0.05 - 0.15  
> =\> 2.77555756156289e-17
> 
> You’re actually gaining money here.

Indeed.

The critical take-home lesson:

Floating point arithmetic only approximates arithmetic with real  
numbers.

Never write code which assumes that math with floating-point code  
will observe the normal laws of arithmetic (most common mistake:  
assuming == is useful for testing the equality of two  
floating-point results).

If you’re unsure, it might be better not to use floating-point at  
all.

-mental

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 16, 2005, 11:15pm UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/12 "2005-12-16T23:15:41Z")

</div>

Joe Van D. wrote:

> On 12/12/05, removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > If you’re doing anything that matters, don’t use floats for  
> > currency. There are a lot of really nasty subtle issues that will  
> > lose money between the cracks.  
> > […]
> 
> What cracks can I lose money through?

It’s not just that; your program logic can also behave unexpectedly.  
e.g.

irb\> 1.20 - 1.00 == 0.20  
=\> false

Use BigDecimal for currency. I’ve just finished some new Rdoc  
documentation for it which will hopefully be added to [ruby-doc.org](http://ruby-doc.org) and  
the 1.9 release, and can forward you a copy if you like.

mathew

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 16, 2005, 11:42pm UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/13 "2005-12-16T23:42:54Z")

</div>

mathew wrote:

> Use BigDecimal for currency. I’ve just finished some new Rdoc  
> documentation for it which will hopefully be added to [ruby-doc.org](http://ruby-doc.org) and  
> the 1.9 release, and can forward you a copy if you like.

Hi mathew,

Excuse my ignorance, but I’m wondering what BigDecimal does different  
than the built-in integer types?

Thanks,  
Steve

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 13, 2005, 9:34pm UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/14 "2005-12-13T21:34:32Z")

</div>

Joe Van D.:

> What cracks can I lose money through?

irb\> 0.2 - 0.05 - 0.15  
=\> 2.77555756156289e-17

You’re actually gaining money here.

Malte

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 16, 2005, 11:45pm UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/15 "2005-12-16T23:45:55Z")

</div>

On Dec 16, 2005, at 4:39 PM, Stephen W. wrote:

> mathew wrote:
> 
> > Use BigDecimal for currency. I’ve just finished some new Rdoc  
> > documentation for it which will hopefully be added to [ruby-doc.org](http://ruby-doc.org)  
> > and the 1.9 release, and can forward you a copy if you like.
> 
> Hi mathew,
> 
> Excuse my ignorance, but I’m wondering what BigDecimal does  
> different than the built-in integer types?

It doesn’t use floating point arithmetic. That means it is accurate,  
but slower.

James Edward G. II

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 17, 2005, 12:01am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/16 "2005-12-17T00:01:00Z")

</div>

James Edward G. II wrote:

> On Dec 16, 2005, at 4:39 PM, Stephen W. wrote:
> 
> > Excuse my ignorance, but I’m wondering what BigDecimal does different  
> > than the built-in integer types?
> 
> It doesn’t use floating point arithmetic. That means it is accurate,  
> but slower.

Hi James,

I think you misread my question. I realize the difference between  
Integer and FP math, I even explained it earlier in this thread.

I’m asking why one would use BigDecimal, specifically, as opposed to the  
built-in Integer types?

Thanks,  
Steve

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 17, 2005, 12:04am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/17 "2005-12-17T00:04:00Z")

</div>

On Dec 16, 2005, at 4:58 PM, Stephen W. wrote:

> I think you misread my question.

Sorry about that.

> I’m asking why one would use BigDecimal, specifically, as opposed  
> to the built-in Integer types?

Well, BigDecimal lets you work with decimals, but will be slower.  
Integers will be faster, but you’ll need to handle the conversions,  
as needed.

Hope I got it right that time. 😉

James Edward G. II

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 16, 2005, 11:51pm UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/18 "2005-12-16T23:51:26Z")

</div>

Hunter’s Lists wrote:

> Howdy,
> 
> I have some methods that manipulate floats that represent a currency  
> amount.
> 
> I often end up with more precision than I need, i.e.: $9.756.
> 
> What is the best way to scale that to 9.76?

I think this has already been covered, but:

“Money does not float!”

🙂

> Cheers.

E

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 17, 2005, 12:13am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/19 "2005-12-17T00:13:08Z")

</div>

Stephen W. wrote:

> I’m asking why one would use BigDecimal, specifically, as opposed to the  
> built-in Integer types?

One would use BigDecimal instead of Fixnum or Bignum when one is going  
to do some operation that might produce a fraction. If you’re certain  
your operations will always result in whole numbers, though, I don’t see  
a point in dragging in BigDecimal.

–  
Neil S. - removed\_email\_address@domain.invalid

‘A republic, if you can keep it.’ – Benjamin Franklin

---

<div class="post-metadata">

**Author:** ![HunterSs\_Lists](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/6bbea6/32.png) [@HunterSs\_Lists](https://www.ruby-forum.com/u/HunterSs_Lists)\
**Post date:** [December 17, 2005, 12:28am UTC](https://www.ruby-forum.com/t/using-float-for-currency/50102/20 "2005-12-17T00:28:44Z")

</div>

James Edward G. II wrote:

> Well, BigDecimal lets you work with decimals, but will be slower.  
> Integers will be faster, but you’ll need to handle the conversions, as  
> needed.

Ahh, I see what BigDecimal is now. Think I’d rather just use cents and  
Integers.

–Steve

[Next page](https://www.ruby-forum.com/t/using-float-for-currency/50102.md?page=2)
