9 ms·
Decimal numbers are not conceptually any more or less exact than binary numbers. For example, you can't represent 1/3 exactly in decimal, just like you can't re
by umanwizard 7y ago
Decimal numbers are not conceptually any more or less exact than binary numbers. For example, you can't represent 1/3 exactly in decimal, just like you can't represent 1/5 exactly in binary.
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.
- DannyB2 7y agoThe real lesson is, no matter what base (radix) you use, floating point math is inexact. 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.
- seppel 7y ago> The real lesson is, no matter what base (radix) you use, floating point math is inexact. 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.
- umanwizard 7y agoI think what that commentator meant is that floating-point math is not an accurate model of rational-number arithmetic, not that there aren't certain computations that are in fact exact. (As you point out, there are: 1.5 + 4.25 is indeed exact)
- seppel 7y ago> is that floating-point math is not an accurate model of rational-number arithmetic 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.
- umanwizard 7y agoUnsigned integer math (on typical machines) is an exact model of the ring of integers modulo 2^64. Floating point arithmetic is not an exact model of anything with nice properties that people are used to from algebra.
- seppel 7y ago> Integer math (on typical machines) is an exact model of the ring of integers modulo 2^64. 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).
- umanwizard 7y ago> And even this is only true if you retrict yourself to unsigned integers 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.
- swebs 7y agoA 32 bit floating point number can only have around 4 billion unique values, yet must represent numbers from 10^38, to very small decimals. 99.99999% of numbers in this range cannot be accurately represented in floating point form. 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.
- bspammer 7y agoTo be mathematically pedantic, 100% of numbers in that range cannot be accurately represented in floating point form.
- seppel 7y ago> yet must represent numbers from 10^38 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.
- johnday 7y agoThere's no such thing as a "problem of base2". Base 2 is an ineffable fact of the universe, and it is neither virtuous nor problematic. All the problems you are describing are problems of floating-point arithmetic.
- seppel 7y ago> There's no such thing as a "problem of base2". 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.
- NohatCoder 7y agoMoney are really best dealt with as integers, any time you'd use a non-integer number, use some fixed multiple that makes it an integer, then divide by the excess factor at the end of the calculation. For instance computing 2.15% yearly interest on a bank account might be done as follows: 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 Balance should always be expressed in the smallest fraction of currency that we conventionally round to, like 1 yen or 1/100 dollar. Adding in half of the divisor before dividing effectively turns floor division into correctly rounded division.
- jgtrosh 7y agoSounds like fractions cleanly describe what you're saying? 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.
- NohatCoder 7y agoThis only for dealing with actual money, generally our banking systems have rounding rules that prevent the fractions from getting out of hand. If you are running an economic simulation you generally don't have to worry about rounding, the whole thing is only approximate anyway.
- hermitdev 7y agoYup. Once worked on a big project with one of the largest US exchanges. We were migrating large OTC (over the counter) CDS (credit default swaps) contracts to standardized centralized contracts. We were testing with large contracts, millions of contracts worth trillions of dollars. I was off by a single penny and failed the test. Took a while to find, but it was due to a truncate to zero instead of a proper round. I was using a floating point type instead of a proper decimal. Dont think the language I was using had a proper decimal type at the time, though it does now, 11 years later.
- rstuart4133 7y ago> Decimal numbers are not conceptually any more or less exact than binary numbers. 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.