News for hackers. Stuff that matters.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by CamperBob2 on Wednesday February 08, 2023 @01:19PM (#34712315)
PS. If you design software that works with money amounts, always use fixed point decimals. Don't use floats, it's just wrong!

Eh, doubles are fine for (most) currencies. Just don't do comparisons without appropriate epsilons.

People who compoare floating-point numbers for equality are going to make other fundamental mistakes with whatever data type you force them to work with.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by radu_floricica on Wednesday February 08, 2023 @01:57PM (#34712929)
I thought that until literally two days ago. Turns out that if you sum a bunch of 0.37 (not even huge numbers, just around a few thousand) you end up with differences on the order of 10-20. Both in mysql and in Java. No, this doesn't makes sense to me either - the differences should be a LOT farther than 3 digits. And yet.

You should have seen my face when debugging this.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by zeven7 on Wednesday February 08, 2023 @02:16PM (#34713281)
I'm curious about this. Could you provide an example?

Here's what I'm seeing:

---

JavaScript

    (function() {
      let inc = 0.37;
      let times = 5000;
      let total = 0;
      for (let i = 0; i < 5000; i++) {
        total += inc;
      }
      console.log('expected:', inc \* times);
      console.log('actual:', total);
    })();
expected: 1850

actual: 1849.9999999997679

---

Java

    public class MyClass {
        public static void main(String args[]) {
            double inc = 0.37;
            double times = 5000;
            double total = 0;
            for (double i = 0; i < 5000; i++) {
                total += inc;
            }
            System.out.println("expected: " + (inc \* times));
            System.out.println("actual: " + total);
        }
    }
expected: 1850.0

actual: 1849.9999999997679

---

update: Changing `double` to `float` in Java yields:

expected: 1850.0

actual: 1849.9778

and maybe that lines up with what you meant by "the differences should be a LOT farther than 3 digits", though it's hard to tell what you mean by "differences on the order of 10-20".

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by HNDen21 on Wednesday February 08, 2023 @03:37PM (#34714662)
same in SQL Server

   declare @i float =0.37,@times int = 0,@total float = 0

   while @times < 5000
   begin
   set  @total+=  @i
   set @times +=1
   end

   select @total
1849.99999999977

or

   select sum(t) from(
   select top 5000 convert(float, 0.37) t 
   from sysobjects a cross join sysobjects b) z
1849.99999999977
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by radu_floricica on Thursday February 09, 2023 @02:31AM (#34720812)
something like, in mysql: create table t ( value double(10,2) not null ); put a bunch of values, something like 15k with maybe half of them being 0.37.

Do the sum two ways:

- export them in excel and do a sum

- select sum(value) from t

and you get two different values, with a difference of something like 15.

Replace double(10,2) with decimal(10,2), and the sum(value) works correctly.

I still have no idea why this happens. I could expect a tiny difference, and code like your above will indeed give differences like this, well under 1.0, but my particular scenario had differences many orders of magnitude higher. Still can't explain.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by archi42 on Thursday February 09, 2023 @04:21AM (#34721533)
something like 15k with maybe half of them being 0.37

Oh, that's something entirely different. If some of your other numbers are much larger than 0.37, you will run into a different kind of problem.

You know about exponent and mantissa? Adding a value with a small exponent to a value with a big exponent will cause imprecisions. In extreme cases the result is just the bigger number.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by worik on Wednesday February 08, 2023 @01:58PM (#34712939)
Yes

But actually, since fixed point decimals are not all ways available use the smallest unit of account, not smallest legal tender, and integer arithmetic

And learn how to round

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by adamwk on Wednesday February 08, 2023 @04:07PM (#34715185)
Smallest unit also has issues. For instance the Indonesian rupiah technically is made up of 100 sen, but the currency is so inflated nobody uses it and currency libraries behave differently (even different versions of the same library). We had a bug where different OS versions provided different values when normalizing it to a smallest unit integer.

If you really don’t have access to a decimal type I think the best solution is to convert it to micro-units (price * 10^6). This is what Android does in its billing library.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by worik on Wednesday February 08, 2023 @06:42PM (#34717422)
Use sen. It can be transferred by bank transfer.

What people use as cash is a distraction, generally

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by stevoski on Wednesday February 08, 2023 @02:02PM (#34712991)
Somebody is wrong on the Internet today. Very wrong.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by Kon-Peki on Wednesday February 08, 2023 @03:18PM (#34714334)
If I want to know the monthly payment on a $500,000 mortgage for 30 years at 6%, should I use:

1. Decimal math

2. Binary floating point math

3. Domain knowledge trumps all; it makes no difference

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by gibspaulding on Wednesday February 08, 2023 @04:21PM (#34715379)
Then of course you'll have to work back to compute an APR for that by a crazy iterative formula outlined by the US gov. Which would you use for that process?
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by meese712 on Wednesday February 08, 2023 @10:32PM (#34719419)
irr? The library we use uses doubles https://github.com/eric-malachias/irr. We also use doubles for the amortization table and doubles for everything.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by meese712 on Wednesday February 08, 2023 @10:22PM (#34719364)
Oh hey I work in mortgage! We use plain old doubles for everything and there's some rounds in there and occasionally an exotic round to the nearest 1/8th. Everything ends up matching fine where it needs to.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by wyager on Wednesday February 08, 2023 @02:14PM (#34713228)
Currency quantities are inherently exact. If you're doing epsilon comparisons on currency quantities, you are making a fundamental ontological error.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by CamperBob2 on Wednesday February 08, 2023 @03:38PM (#34714674)
Nobody gives a hoot about 0.000001 cents. Round to the nearest 1/100 cent after adding or subtracting, and you will be fine in 99.99999% of applications.

The cardinal sin isn't using doubles for currency; it's using them without understanding either the tool or the job that you're asking the tool to perform.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by wyager on Wednesday February 08, 2023 @06:48PM (#34717487)
You've clearly never worked with accountants.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by CamperBob2 on Wednesday February 08, 2023 @08:11PM (#34718336)
[Citation needed]
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by mths on Wednesday February 08, 2023 @10:11PM (#34719303)
You've clearly never worked with accountants. [1]

[1] https://news.ycombinator.com/item?id=34717487

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by CamperBob2 on Wednesday February 08, 2023 @11:54PM (#34719919)
I don't know what I expected
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by 8n4vidtmkvmk on Thursday February 09, 2023 @12:16AM (#34720054)
I've been using doubles for currency knowing full well that i probably shouldn't. for 8 years now. so far I've only noticed being off by a cent here and there. yep.. just don't care. will cost more than a penny to fix it now.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by lmm on Wednesday February 08, 2023 @10:49PM (#34719536)
Depends what you're doing with them. A value at risk calculation gives you a currency-dimensioned result that's hard to represent exactly, for example.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by wyager on Thursday February 09, 2023 @09:26AM (#34724354)
Yes, a more precise statement is "exact currency amounts form a group under addition" - once you depart from group operations (e.g. multiplication by non-integral scalars) you can start to consider floats.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by goto11 on Thursday February 09, 2023 @02:44PM (#34730143)
Accounting and banking does not allow epsilons. You always need to be able to account for every last cent on every account and every transaction. And the precision you need is fixed, so there is no purpose in using floating points.

I guess there are some contexts where floats are fine for monetary amounts, for example if you make economic forecasts or simulations.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by CamperBob2 on Saturday February 11, 2023 @04:25PM (#34756527)
You always need to be able to account for every last cent on every account

Then that's your epsilon. Or, more reasonably, one or two powers of 10 further down. Absolutely nobody cares about a millionth of a cent. A few people care about a thousandth, though. Most people get antsy if you can't pin a calculation down to the nearest cent.

Floats are pretty much never fine for currency, but doubles are usually OK. There's a world of difference between a 24-bit mantissa and a 53-bit mantissa.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by goto11 on Saturday February 18, 2023 @12:12PM (#34848620)
The problem is that some decimal amounts, e.g. 10 cent ($ 0.10) cannot be represented precisely using binary floating point. It doesn't matter how many bits you use since 0.1 have an infinite expansion in binary.

This is exactly what the article describes and explains. 10 cent plus 20 cent does not equal 30 cent, when using binary floating point. This is not acceptable in accounting, since at one point the error may accumulate and cause an error at the size of a cent (or more).