News for hackers. Stuff that matters.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by dgudkov on Wednesday February 08, 2023 @01:05PM (#34712084)
Both Excel and Google Sheets return FALSE for this expression:

    2.03 - 2 - 0.03 = 0
The vast majority of data transformation and BI tools (Power BI, PowerQuery, Tableau, etc.) return FALSE for this expression:

    0.1 + 0.2 = 0.3
That's because they use floats instead of decimals and that introduces subtle errors in data. These errors usually never get noticed because everyone doesn't expect errors in basic math. It's a mystery to me why most commercial software intended for business and financial calculations don't use fixed point decimals. My post about this: https://www.linkedin.com/feed/update/urn:li:activity:7028101...

PS. If you design software that works with money amounts, always use fixed point decimals. Don't use floats, it's just wrong!

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).

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by hinkley on Wednesday February 08, 2023 @01:53PM (#34712851)
I learned about binary coded decimal in school and it was the weirdest thing but is pretty good for money.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by ElectricalUnion on Wednesday February 08, 2023 @06:06PM (#34716927)
Doing mostly bcd math is unfortunately one of the reasons why the old style HP calculators were dog-slow. It also did not help that those old calculators like rounding values too much.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by jdmichal on Wednesday February 08, 2023 @06:12PM (#34717011)
Not calculators, but I did some tests a few years ago, and I'm pretty sure the BCD instructions on modern processors are no longer implemented in hardware. They were no different than using an equivalent string of other opcodes.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by ezfe on Wednesday February 08, 2023 @01:54PM (#34712883)
Numbers (from Apple) returns TRUE for both expressions you list
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by Kon-Peki on Wednesday February 08, 2023 @02:27PM (#34713462)
Objective-C has a really nice decimal math library. Last I looked (it’s been a while), Swift didn’t. It might have one by now.

Years ago, I had a few apps in the App Store that made extensive use of it. It really was very nice to work with.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by arcticbull on Wednesday February 08, 2023 @02:51PM (#34713870)
Swift has the same functionality in the Decimal type.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by Kon-Peki on Wednesday February 08, 2023 @03:15PM (#34714273)
Thanks! It looks like that was added in Swift 3. That was a long time ago. I guess I’m just really old ;)
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by sheetjs on Wednesday February 08, 2023 @02:17PM (#34713287)
Under the hood, modern Numbers stores values in Decimal128 (16 bytes)
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by Salgat on Wednesday February 08, 2023 @04:35PM (#34715576)
So people understand, Decimal type is not fixed point, but rather is a floating-point type that uses base 10 instead base 2. This means that if you do 1.0/3.0*3.0, you still get 0.999999~.

Example: http://tpcg.io/_A0IXQJ

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by SnowHill9902 on Wednesday February 08, 2023 @02:23PM (#34713392)
The equality operator should not be implemented for the float type to being with. Money amounts should use integer.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by svachalek on Wednesday February 08, 2023 @02:35PM (#34713609)
A true decimal type is better than integer, if your language supports it.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by t8sr on Wednesday February 08, 2023 @03:16PM (#34714304)
Decimals are notoriously hairy to implement and it's not obvious how they should behave when they run out of precision. Integers are almost always the better choice when the decimal is fixed, such as with currency.

(I guess it depends on what you mean by "true" decimal. If you meant BigNum, then sure.)

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by tremon on Wednesday February 08, 2023 @03:42PM (#34714736)
Decimals are notoriously hairy to implement

Only floating-point decimal is hairy. Fixed-point decimal is hardly more difficult than integer math.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by t8sr on Wednesday February 08, 2023 @04:00PM (#34715057)
If you simply look at any of the real world implementations, you'll see it's not so easy. Rust has a few readable and educational crates that implement decimals, if you want to take a look.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by int_19h on Wednesday February 08, 2023 @05:41PM (#34716612)
Decimal floating point is fine so long as you constrain the exponent such that delta between two consecutive valid numbers can never be greater than 1 (that is, there should never be any implicit trailing zeroes). .NET Decimal type is a good example.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by ElectricalUnion on Wednesday February 08, 2023 @06:00PM (#34716846)
> Decimals are notoriously hairy to implement

That's because the binary is implemented in hardware for you; and those days you can usually (but not always) trust the hardware to do the correct thing; if you have to implement it youself (say, deterministic, side-effect free math), it's also hairy.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by midoridensha on Wednesday February 08, 2023 @10:09PM (#34719293)
A lot of times, though, currency is not fixed. Stock share prices can be in fractions of a cent; per-unit cost numbers can easily have fractional cents too, just for a couple of quick examples. Sure, if you're just looking at your bank account, or itemizing actual transactions, they're going to be in whole cents only, but lots of financial calculations need more precision than this.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by piaste on Thursday February 09, 2023 @04:23AM (#34721541)
Having different numeric types for currency amounts (integer) and for costs or prices (floating point, whether decimal or binary) is not undesirable. Heck, it's very likely a bonus.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by mcv on Thursday February 09, 2023 @06:55AM (#34722642)
That sounds like a recipe for disaster. If you have fractional unit prices, and multiply by the number of units, floats can still give you errors. No, fixed decimal types definitely have their uses.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by Salgat on Wednesday February 08, 2023 @04:41PM (#34715670)
A fixed point type is even better. Decimal type is tricky because using base 10 and a larger precision does hide some bugs giving a false sense of security for what Decimal type can do.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by Kon-Peki on Wednesday February 08, 2023 @03:00PM (#34714001)
> If you design software that works with money amounts, always use fixed point decimals. Don't use floats, it's just wrong!

Don’t write with such certainty! Decimal math is great advice for many/most situations, but what if you have a LOT of numbers and not a lot of time? That big number crunching GPU is not available if you take this approach.

Numerical Methods was the most difficult CS course I took in university and also the one I did the worst in. And of course it was an elective, or else they wouldn’t have graduated many people at all. If you’re doing a lot of number crunching stuff, maybe you should ask people that know how to number crunch to design your system so it has the smallest errors :)

PS - I’m not the person for that job!

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by t8sr on Wednesday February 08, 2023 @03:15PM (#34714272)
I am almost completely certain that neither Google Sheets, nor Excel use that "big number crunching GPU" for anything float-related.

Just getting the data to the GPU for a compute shader to run on it would take longer than just doing on the CPU in almost every case.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by bruce511 on Thursday February 09, 2023 @12:56AM (#34720255)
I'm not sure if the parent poster meant GPU or CPU. While yeah GPU has good floating point math, you probably don't use that for things like excel.

On the other hand the CPU has floating point math too, and floating point math is MUCH faster than decimal math.

So his point holds if you replace GPU with CPU, but his use of GPU is likely inaccurate.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by t8sr on Thursday February 09, 2023 @04:32AM (#34721610)
Ah, yeah. The performance of modern FPUs really kills, and it's changing a lot of the assumptions I used to have about performance.

Anecdote: In state of the art physics code, it's common to use integers for coordinates [1]. Recently, I was working on a BSc. toy project, and I used ints for coordinates as is common. With both ints and floats it's important to be careful around functions like `tan` that go to infinity, but of course floats are more forgiving, so I prototyped some of the code using doubles.

I ended up comparing performance and it wasn't even funny. Double precision arithmetic was anywhere between 3x (where a good int algorithm is known) all the way to 100x faster (if the int algorithm is cordic, for example) than integers.

1: Springel 2013 p. 1-82 https://wwwmpa.mpa-garching.mpg.de/gadget4/gadget4-code-pape...

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by albrewer on Thursday February 09, 2023 @11:44AM (#34726795)
> you probably don't use that for things like excel

I'm not sure when I read it, but long ago I read some kind of AMA from a MS engineer working on Excel saying that his greatest achievement was working on the team that made the Excel's DAG solver trivially parallelizable. In the same thread, he mentioned that offloading to the GPU was being looked into. I guess it never came to fruition.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by Kon-Peki on Thursday February 09, 2023 @12:00PM (#34727089)
> use of GPU is likely inaccurate.

The number 1 supercomputer in the world has 8 million GPU cores (or is it 8 million GPUs? Execution Units?) and 600k CPU cores.

They are doing floating point math on GPUs. Numerical analysis [1] is used to create the best accuracy possible. This is something that has been done for thousands of years, basically since math has had problems with no "exact" solution.

[1] https://en.wikipedia.org/wiki/Numerical_analysis

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by int_19h on Wednesday February 08, 2023 @05:38PM (#34716560)
We should be optimizing for correctness over performance by default, though. People who need binary floating point for perf reasons should already know the tradeoffs.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by Karellen on Thursday February 09, 2023 @06:49AM (#34722577)
I remember reading on a forum many years ago where one person was rationalising performance over correctness, someone replied that if their code didn't have to be correct they could get the answer in clock 1 cycle with zero memory usage. :-)
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by gorgoiler on Wednesday February 08, 2023 @03:10PM (#34714180)
Paging Colin Percival to talk about picodollars. The medium strength advice on this topic is to use integer math with cents as your unit. Colin’s advice is to choose the smallest possible unit you can that will avoid overflow (I think) hence why he prices tarsnap in picodollars: https://www.tarsnap.com/picoUSD-why.html
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by cperciva on Thursday February 09, 2023 @10:52AM (#34725774)
Picodollars are awesome, but I actually do Tarsnap's accounting in attodollars since it's convenient to use a 64-bit unsigned integer to represent units of 10^-18.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by t8sr on Wednesday February 08, 2023 @03:20PM (#34714372)
The really surprising* thing is that Google Sheets uses floats for everything. Back in the day, I was using Sheets to do some statistics about (IIRC) kernel ASLR on macOS, and I was surprised to see kernel pointers ending in odd numbers. Of course only after I'd wasted 2 hours on it.

Boy, did I file a pissy bug with the Sheets team that day, and then requested an Excel install I never let go of since that day.

* I guess it's maybe not surprising to js developers, but don't most modern browsers have integers by now?

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by altruios on Wednesday February 08, 2023 @04:47PM (#34715755)
besides bigInt...

What numbers in javascript are not actually doubles (what js uses under the hood for every number)?

You can convert them from doubles to 32-ints apparently by some bitwise hacks like (I'm pretty sure they still are 'doubles' though - and it just does some rounding tricks)

``` |0 //signed >>>0 //unsigned ```

So any webapp (google sheets) will likely have problems related to floating point math.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by ElectricalUnion on Wednesday February 08, 2023 @05:56PM (#34716793)
> You can convert them from doubles to 32-ints

You can use the native BigInt arbitrary-precision integers and ignore all "fits under this arbitrary limited bit slice" problems.

You can use doubles as a integer directly, in a safe way, until you touch the 53 bits barrier (Number.MIN_SAFE_INTEGER === -9007199254740991 or Number.MAX_SAFE_INTEGER === 9007199254740991).

None of those really are (modern) webapp issues.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by jkaptur on Wednesday February 08, 2023 @04:49PM (#34715794)
How do Sheets and Excel differ in this regard? How did using floats cause some number to be odd?
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by jdmichal on Wednesday February 08, 2023 @06:03PM (#34716888)
GP didn't say odd, or at least not numerically odd, but rather "ending in impossible digits".

Floats have varying precision, not uniform. The closer the number is to zero, the more precision it has. There's a point where the precision is so low that it only covers whole numbers, and then a point after that where the precision is less than whole numbers.

Given the context of pointers, it's quite possible that they were large enough to reach that less-than-whole-number-precision range.

EDIT: For 32-bit floats, that's apparently any number above 16,777,216. Which seems surprisingly small to me. For 64-bit doubles that goes to 9,007,199,254,740,992.

https://blog.demofox.org/2017/11/21/floating-point-precision

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by jkaptur on Wednesday February 08, 2023 @07:57PM (#34718205)
I think the comment may have been edited ;)

Anyway, yes, that's all true. Excel, Sheets, JavaScript numbers, Java doubles, Python floats, and so on all work this way. That's why I asked how switching spreadsheet implementations solved the problem.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by jdmichal on Thursday February 09, 2023 @12:24PM (#34727519)
Ah, sorry for that I must have seen the updated one.

I agree with you that switching programs that are all using the IEEE floating-point formats with the same underlying hardware implementations should result in the same answers.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by ElectricalUnion on Wednesday February 08, 2023 @05:48PM (#34716698)
> Google Sheets uses floats for everything (...) and then requested an Excel install

But Excel also uses floats (as in, Single-precision floating-point format, aka float32), because of "compatibility with Lotus 1-2-3".

https://softwarerecs.stackexchange.com/questions/53292/any-s...

https://learn.microsoft.com/en-us/office/troubleshoot/excel/...

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by mananaysiempre on Wednesday February 08, 2023 @10:29PM (#34719399)
Excel uses floats in its own ways that even experts on floating-point arithmetic find inscrutable[1].

[1] https://people.eecs.berkeley.edu/~wkahan/Mindless.pdf, §2

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by t8sr on Thursday February 09, 2023 @04:20AM (#34721518)
Ah, but it used ints (or bignum) to represent my pointer values, instead of silently losing precision. This is an anecdote, maybe there are other gotchas I am blissfully ignorant of. (Also, this was 8 years ago.)
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by roxgib on Wednesday February 08, 2023 @03:55PM (#34714961)
Even if you set the data format to 'currency' it still returns false (in Google Sheets). I realise they probably want consistency but it's weird they don't have an option to use a decimal type.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by codetrotter on Wednesday February 08, 2023 @04:12PM (#34715252)
It is my impression of most spreadsheet software that the “data format” is more about display, and not about actually strongly typed representations of the data.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by vba616 on Wednesday February 08, 2023 @05:03PM (#34716013)
> If you design software that works with money amounts, always use fixed point decimals. Don't use floats, it's just wrong!

I find it funny the gap between what computer people think finance requires and actual practice.

The tax people in the US generally aren't interested in pennies any more! And when you use tax software that throws away the pennies before the final results, then your sums may very well not match the forms whose information is independently reported to the IRS, by well over a dollar. But nobody cares!

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by sowbug on Wednesday February 08, 2023 @05:17PM (#34716257)
No need to invent a divide between "computer people" and "tax people," whoever they are. Maybe the IRS allows small errors because bugs attributable to floating-point precision are too hard to fix.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by jdmichal on Wednesday February 08, 2023 @05:59PM (#34716837)
AFAIK the IRS has always been accepting of truncating / rounding values to full dollars and discarding cents. It's certainly been that way for the decades that I've been doing taxes.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by jay_kyburz on Wednesday February 08, 2023 @11:22PM (#34719717)
In Australia the tax office doesn't event let you enter cents in online fields.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by vba616 on Friday February 10, 2023 @10:56PM (#34749435)
My point was that (at least some) standard US tax software rounds to dollars on intermediate results, apparently permitted and required by the IRS.

...while financial institutions send reports to clients and the IRS that have the totals rounded only at the end, meaning the things that are supposed to match don't and can't.

Even though they are both in dollars, they are not consistent even to the nearest dollar.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by srcreigh on Wednesday February 08, 2023 @07:03PM (#34717653)
In scheme, (= (+ (/ 2 10) (/ 1 10)) (/ 3 10)) is #t.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by jdsully on Wednesday February 08, 2023 @08:01PM (#34718246)
Because perf was super important for a spreadsheet in the 90s, and now back compatibility is super important.

You do not want your numbers changing in the next version of Excel.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by cm2187 on Thursday February 09, 2023 @02:39AM (#34720861)
I don't think he meant Excel. You can't use decimals in excel. First you will overflow immediatly (like multiply two numbers in trillons). Then your rounding will kill small amounts (like percentages). There is no alternative to floats in excel.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by jdsully on Thursday February 09, 2023 @04:18AM (#34721506)
The predecessor to excel (multi plan) used binary coded decimal.

But there’s nothing stopping you from doing arbitrary precision decimal in excel except back compatibility (and all the thousands of lines of code looking for a float).

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by lr1970 on Wednesday February 08, 2023 @08:35PM (#34718553)
> PS. If you design software that works with money amounts, always use fixed point decimals. Don't use floats, it's just wrong!

Fundamental reason being that powers of 1/10 in decimal fractions are not always representable by powers of 1/2 in binary. Specifically 0.1 = 0b00011001100110011... is infinitely long binary string. Truncating it to any finite bit-width like 32 or 64 bits always introduces an error.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by SideQuark on Wednesday February 08, 2023 @09:24PM (#34718978)
Fixed point fails for just about any financial calcs beyond simple addition. Try doing common compound interest calcs for example, and you'll get much worse answers.

The correct answer is to use floating point and to understand it and numerical software before doing it. If you don't have a decent understanding of numerical analysis, don't write important numerical software.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by PeterisP on Wednesday February 08, 2023 @10:12PM (#34719312)
Well, but the "common" compound interest calcs aren't how compound interest is actually calculated. You use floating point to calculate the amount due, but once you do, you round to a fixed point (e.g. whole cents) and that's it, that's the final truth. The interest accrued, interest due and interest paid out is a fixed point value by definition. And then for the next interest period you start with that rounded off value as the basis for calculating the next interest which compounds.

So yes, if you use fixed point you obviously get different results, but you won't get correct results according to what's required by accounting standards unless you truncate to fixed point when needed. It's not that this difference is large - after all, it's about rounding off fractions of a cent - but accounting does need to be exact.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by SideQuark on Thursday February 09, 2023 @02:53PM (#34730305)
> aren't how compound interest is actually calculated.

Completely depends - package them in tranches to sell to secondary markets by the thousands - then you do exactly as I pointed out. Or if you're doing Monte Carlo futures projections modeled as compound interest and only need the value at a future time.... Or any of thousands of financial modeling needs....

If you're printing monthly bills for consumers then you round, but only at output, and only for viewable parts.

So you cannot claim things are not computed this way - it depends on the financial application you're working on,

>So yes, if you use fixed point you obviously get different results, but you won't get correct results according to what's required by accounting standards

Ha - which standard are these? Care to cite them? I've been through this space a long time, and every time someone tells me there is a standard and I ask them for it they soon realize there is no gold, single standard. There are zillions of acceptable choices. There are ones for consumers, ones for intrabank, interbank, fed to bank, loans, mortgagaes, taxes, and on and on. There is no "correct results according to what's required by accounting standards ".

Please cite your standards that apply to all these cases.

Have you worked in finance on numerical financial software?

>you round to a fixed point (e.g. whole cents) and that's it, that's the final truth

Having done numerical stuff, including finance for decades, you simply write the entire codebase in floating point, being sure to do proper analysis that things handle ranges correctly.

Then, and only for output, do you snap to desired observable precision. Never ever even once do you round something to make it look pretty, then jam it back into calculations.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by PeterisP on Friday February 10, 2023 @07:48PM (#34748248)
The difference seems to be that you are talking about modeling and analysis and I was talking about calculating actual interest, as in the interest that is actually owed for a particular loan or contract (i.e. every particular contract) and properly accounting for that.

It doesn't matter if the interest is calculated for consumers, intrabank, interbank, fed to bank, loans, mortgages, taxes - the interest rates and interest periods and interest day basis and all kinds of details may vary, and of course accounting standards vary between countries, but the core principles are the same that it all eventually comes up to some amount of money owed to the counterparty - measured in whole cents or perhaps whole dollars or roubles or whatever, but never an arbitrary-precision float. You can't get to a final compounded result "only for output" because when interest compounds (for example, monthly) then at every such point you do have actual "intermediate output" which materializes into a customer-visible change of balance from which the next period's interest is then calculated, and that intermediate output gets rounded because that (unlike estimates or models) is a specific balance owed and it is denominated in a currency with fixed, limited precision. And so after many such steps, the total actual compound interest - i.e. the actual dollars and cents paid by (or to) the counterparty - is slightly different from what the common modeling approach gets if e.g., as you state, it does rounding only for the final output. The difference is tiny, so there is no problem for modeling to ignore it, but actual financial systems (i.e. tracking facts of money owed, not doing estimates and models for decision support) do have to come down to a rounded fixed-precision number owed for every contract at the end of every day.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by wruza on Thursday February 09, 2023 @04:08AM (#34721439)
There’s also a middle ground, which I find more useful than either full-floating or full-fixed. Use floating for intermediate calculations and fixed-only with autorounding for “fields”. So that:

  var t = obj.x // fixed -> fp
  for (<n times>) {
    t += 0.1
  }
  obj.x = t // adds exactly n/10
The key observation is that intermediates don’t float free long enough before being assigned back to a fixed storage. So the error has no chance to accumulate. But still can manifest in comparisons. If necessary, floating point can be replaced with precise enough fixed point for intermediates (at a cost, e.g. tens of digits).

The correct answer is to use floating point and to understand it and numerical software before doing it

Yes, but this also has associated costs and risks. Unless you’re pressed against some wall, it’s more safe to offload that to a runtime. Humans are way too unreliable when it comes to understanding numerical software.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by SideQuark on Thursday February 09, 2023 @02:56PM (#34730348)
Never ever ever ever perform summation like that. You just added O(n) error instead of O(1) error.

This is why ad-hoc methods that people feel are ok based on untrained or not-carefully-studied analysis should not write production numerical code.

Just use floating point everywhere, and only output things snapped to whatever resolution you want (and even that is tricky). Otherwise all those fixed to float to fixed to float going on in your code are going to add all sorts of numerical problems - each loses information.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by wruza on Thursday February 09, 2023 @06:29PM (#34733268)
I believe you missed the part where it rounds the error away. Of course for high N it may overflow into a significant part, but that’s 25-30 bits away for `double` and much more for custom non-fixed types, which implies a dataset that a client app wouldn’t be able to handle anyway. Multiplication is another beast, but repeating multiplication doesn’t appear in finance naturally.

In case you did not miss it: I’ve worked with and supported financial systems which do exactly that for a very long time without any micro-numerical issues^. Otoh, floating-point is a constant source of microbugs, unless all your developers are Knuth-level pros who are also versed in consulting and have no monday mornings or deadlines. It doesn’t matter if an error is O(N < 1e6) or O(1) when an underwater comparison to a limit fails and control flow triggers randomly.

^ The last [few] cent problem is usually handled explicitly, either naively (last=rest) or in Bresenham-like way (rarely, when it matters) and is easily catched in an accounting balance when left unhandled

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by SideQuark on Friday February 10, 2023 @05:25AM (#34737877)
>I believe you missed the part where it rounds the error away.

I've been down this argument with other HN commenters some time back and explicitly demonstrated that it fails when you do it this way. It's not worth chasing down all the details again.

The short answer is it will fail, and in unexpected places. The only correct answer when doing this to is do the numerical analysis completely and correctly. This half-assed "it rounds the error away" is completely insufficient (and wrong).

The problem with letting such error slop around in code is that someone will take your code and use it to aggregate 1m loans, then your 25 bits of safety just became real money. Then someone will leverage that routine and add more problems.

When you build the lowest pieces so sloppily, it quickly contaminates the whole system. Make each piece as numerically solid as possible, otherwise you will get bitten.

If you have not proven your algorithm correct using numerical analysis for this stuff, it is not correct. End of story.

>but repeating multiplication doesn’t appear in finance naturally

Yes it does - compound interest if you need periods and tables.

And we're in agreement - floating point, not fixed point, is how to do financial calculations. I'm amazed how many people on HN want to argue that fixed point works when it's easy to demonstrate it fails in terrible ways and is significantly more error prone than simply using doubles (or double- or quad- doubles when needed).

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by wruza on Friday February 10, 2023 @08:15AM (#34739238)
Maybe it will, I’m only halfway there. I’ll take the risk, cause your solution (hiring theorem provers) simply costs much more than the risk itself upfront.

Yes it does - compound interest if you need periods and tables.

Only if you don’t round to fixed before capitalizing. But when you don’t, numerically less savvy investors (99.9% of people) would just ask to fix it and stop being so smart. They want deterministic output for any particular end of period.

I see you’re coming from academic side, but real world doesn’t work like that. Nobody’s going to take our algorithms and shove 2^(>20) records of sums greater than $100M into them.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by yafbum on Wednesday February 08, 2023 @09:39PM (#34719094)
This is something people are living with because it's very rare to use exact equality tests on floats in BI applications to begin with. Far more people want to look at the sum of order amounts, or at orders where the amount is within a certain range, than at orders where amount is exactly equal to some random float.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by Out_of_Characte on Thursday February 09, 2023 @01:11AM (#34720330)
It would lead to some hilarious malpractise if anyone understood floating point and stole a billion cents. Things like this has happend and will continue if people arent aware of floating point error.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by DougBTX on Thursday February 09, 2023 @03:15AM (#34721100)
> of floating point error.

Worth noting that this is a risk whenever there is rounding, if this chain of logic happens with cents as ints, it is still wrong:

    1 / 2 => 0
    0 * 2 => 0
Therefore:

    1 == 0
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by dgudkov on Thursday February 09, 2023 @05:21AM (#34721951)
People are living with it until they stumble when an innocent expression

   (a + b) >= c 
suddenly fails to work. For instance, in Excel the expression

   A1-B1-C1 >= 0
returns FALSE when A1=2.03, B1=0.03, and C1=2. Such an expression can be used for instance to filter records that fall within a certain range, and that filter would produce wrong results.
Re:Why does 0.1 and 0.2 = 0.30000000000000004? by cm2187 on Thursday February 09, 2023 @02:31AM (#34720814)
> It's a mystery to me why most commercial software intended for business and financial calculations don't use fixed point decimals

All the reporting software I have seen in banks use decimals for adding numbers.

If you are adding small numbers together, those errors are negligible and get rounded out in the result (you usually can't pay an amount with more than two decimals). It's only a problem if somehow you are doing some calculations that need to be exact on amount large enough that the float rounding starts affecting your pennies.

Financial reporting has materiality thresholds, no one cares about pennies if the size of a balance sheet is trillons, the materiality will likely be in millions, not the least because the numbers will be shown in millions in the financial report and the numbers won't be additive because of rounding) and for a BI tool a number with 12 digits is unreadable and too much information to be useful.

If you are doing pricing, also no one really cares about pennies on a 1 million payment.

> PS. If you design software that works with money amounts, always use fixed point decimals. Don't use floats, it's just wrong!

Well, it depends. If all you do is add and substract numbers, ok, and that's what they typically do. If you need to do any other calculation (and most financial software do), this will bite you as percentages and ratios will be rounded aggressively.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by mcv on Thursday February 09, 2023 @06:49AM (#34722584)
The problem is that fixed decimal types are far less standard in many programming languages. One thing I really loved about Groovy is that BigDecimal is the standard type for decimal numbers. Type `1.5` and you will have a BigDecimal rather than a float in your hands.

Not very suitable for complex scientific calculations of course, but perfect for web development which is more likely to deal with money than scientific calculations.

Re:Why does 0.1 and 0.2 = 0.30000000000000004? by paddim8 on Friday February 10, 2023 @08:15AM (#34739240)
kalker.xyz seems to return true