When handling money, we care about faithfully reproducing the human-centric quirks of decimal numbers, not "being more accurate". There's no reason in principle to regard a system that can't represent 1/3 as being fundamentally more accurate because it happens to be able to represent 1/5.
DaysInYear = 366
InterestRate = 215
DayBalanceSum = 0
for each Day in Year
DayBalanceSum += Day.Balance
InterestRaw = DayBalanceSum * InterestRate
InterestRaw += DaysInYear * 5000
Interest = InterestRaw / (DaysInYear * 10000)
Balance += Interest
> In computing, a fixed-point number representation is a real data type for a number that has a fixed number of digits after (and sometimes also before) the radix point.
> A value of a fixed-point data type is essentially an integer that is scaled by an implicit specific factor determined by the type.
But that practically holds only for a reasonable amount of simple arithmetics. Fractional components tend to grow exponential for many numerical methods repeated multiple times. This can happen if you're describing money and want to apply a complex numerical method from an economics article for whatever purpose. Might be worth it but be careful not to carry ever expanding fractions in your system.
If you are running an economic simulation you generally don't have to worry about rounding, the whole thing is only approximate anyway.
I wish I could up vote you more than once. You are bang on.
The value of floating point is that it can represent extremely huge or extremely infinitesimal values.
If you're working with currency / money, floating point is the wrong thing to use. For the entire history of human civilization, currency has always been an integer type, possibly with a fixed decimal point. Money has always been integers for as long as commerce has existed, and long before computers.
If you're building games, or AI, or navigating to Pluto, then floating point is the tool to use.
This is just not true. If you add 1.5 + 4.25 with IEEE754, there is nothing inexact or rounded. That you cannot exactly represent 0.1 in base2 FP is a problem of base2, not FP.
You get inexact results with FP math for underflows, overflows, or if you don't have enough precision for the result (or an intermediate result). But the same is true for normal integer types.
Well, this is true. But integer math is also not an accurate model of rational-number arithmetic, yet nobody would claim that integer math is inexact.
And even this is only true if you retrict yourself to unsigned integers. For signed integers you have quirks (-0x8000.. = 0x8000..) or minefields (undefined overflow semantics in C, which can yield non-associativity, tests deleted by the compiler, etc.).
And I'd argue that whoever understands the ring of integers modulo 2^64, will also understand the IEEE754 semantics (which are, I agree, sometimes unfortunate. But not inexact).
Fair point. I've edited my comment to include the word "unsigned".
> I'd argue that whoever understands the ring of integers modulo 2^64, will also understand the IEEE754 semantics
I'm an existence proof that that is not true :). Although I'm sure I could learn the IEEE754 semantics if I put enough effort into reading the spec.
But even if they don't know the word "ring", I think most programmers do understand how modulo arithmetic works, and they have algebraic intuitions about it that turn out to be true: both operations are commutative and associative, multiplication distributes over addition, equality of a forumla involving * and + is true if it's true in the actual integers, and so on.
> I'm an existence proof that that is not true :). Although I'm sure I could learn the IEEE754 semantics if I put enough effort into reading the spec.
This was sloppy writing on my side. I wanted to say "whoever understands the ring of integers modulo 2^64, can also understand". And I'm sure you could :)
And you don't even have to read the spec. The core idea (mantissa, exponent, and sign) is super easy and writing a FP emulation for addition and multiplation is a really nice task to understand what is actually going on. The only really unfamiliar idea is binary fractions and I think this is a cool idea to understand on its own.
> But even if they don't know the word "ring", I think most programmers do understand how modulo arithmetic works, and they have algebraic intuitions about it that turn out to be true: both operations are commutative and associative, multiplication distributes over addition, equality is true if it's true in the actual integers, and so on.
Well that is all fine but scrolling back to the grand grand grand parent: That would also be a completely wrong abstraction to model financial stuff. I'm not saying FP is the solution, but for sure modulo arithmetic is also how you not want to do finance :)
That you cannot represent 1/3 as a non-periodic decimal number is a problem of base 10.
That you cannot represent 1/10 as a non-periodic binary number is a problem of base 2.
These are just mathematic facts. Maybe you don't like the world "problem", but it does not change that this is where we are.
The problem that you cannot represent 0.1 in base 2 FP, is a problem of base 2. You can represent it exactly in base 10 FP.
Compare that to a 32 bit integer, which can have 4 billion unique values, and supports numbers from 0 to 4 billion. It's a 1:1 mapping.
No, they don't must represent all number in the range. I don't know where you get from that they must. An integer also can't represent all real numbers in its range.
True but irrelevant. The problem isn't with the math fundamentals, it's the programmers.
The issue is if you get your integer handling wrong it usually stands out. Maybe that's because integers truncate rather than round, maybe it's because the program has to handle all those fractions of cents manually rather than letting the hardware do it so he has to think about it.
In any case integer code that works in unit tests usually continues to work, but floating point code passing all unit tests will be broken on some floating point implementations and not others. The reason is pretty obvious: floating point is inexact, but the implementations contain a ton of optimisations to hide that inexactness so it rarely raises it's ugly head.
When it does it's in the worst possible way. In a past day job I build cash registers and accounting systems. If you use floating point where exact results are required I can guarantee you your future self will be haunted by a never ending stream of phone calls from auditors telling you code that has worked solidly in thousands of installations over a decade can not add up. And god help you if you ever made the mistake of writing "if a == b" because you forgot a and b are floating point. Compiler writers should do us all a favour and not define == and != for floating point.
Back when I was doing this no complier implemented anything beyond 32 bit integer arithmetic, in fact there was no open source either. So you had to write a multi precision library and all expression evaluation had to be done using function calls. Despite floating point giving you hardware 56 bit arithmetic (which was enough), you were still better off using those clunky integers.
As others have said here: if you need exact results (and, yes currency is the most common use case), for the love of god do it using integers.