Live data from Hacker News

0.30000000000000004

0.30000000000000004.com

321–330 of 422 posts

Re: 0.30000000000000004

#321
post #20

The big issue here is what you're going to use your numbers for. If you're going to do a lot of fast floating point operations for something like graphics or neural networks, these errors are fine. Speed is more important than exact accuracy. If you're handling money, or numbers representing some other real, important concern where accuracy matters, most likely any number you intend to show to the user as a number, f…

'Decimal' is a red herring. The number base doesn't matter. (And what are you going to do when you need currency coversions, anyways?) Floats are a digital approximation of real numbers, because computers were originally designed for solving math problems - trigonometry and calculus, that is. For money you want rational numbers, not reals. Unfortunately, computers never got a native rational number type, so you'll ha…

Historically, it's correct-but-too-vague to say computers were for "solving math problems". Historic computer problems should be divided into two types: business problems and scientific/engineering problems. Business problems include things like tabulation and accounting. Programmable digital computers go back at least as far as UNIVAC I, in 1951 (using programmable digital computers for science doesn't go back THAT MUCH farther).

Prior to the IBM/360 (1964), mainframes sold for business purposes generally had no support for floating point arithmetic. They used fixed-point arithmetic. At the hardware level I think this is just integer math (I think?), but at a compiler level you can have different data types which are seen to be fractions with fixed accuracy. I believe I've read that COBOL had this feature since I-don't-know-how-far-back.

This sort of software fixed-point is still standard in SQL and many other places. Some languages, and many application-specific frameworks, have pre-existing fixed-point support. So it's also not accurate to say that you necessarily need to roll your own, though certainly in some contexts you'll need to.

And for money, you very much do not want arbitrary rational numbers. The important thing with money is that results are predictable and not fudgable. The problem with .1 + .2 != .3 is not that anyone cares about 4E-17 dollars, it's that they freak out when the math isn't predictable. Using rationals might be more predictable than using floats, but fixed-point is better still. And that's fixed-point base-10, because it's what your customers use when they check your work.

Re: 0.30000000000000004

#322
post #243
post #67

Earlier quoted context omitted.

It's actually in use in many places, for things like handling currency and money, and for when you get funny corner cases involving rounding such numbers and pooling the change. Whenever I see someone handling currency in floats, something inside me wither and die a small death.

Currency in banking is handled with bigints. Not rationals, just bigints of the smallest unit (i.e., 1 cent). This forces you to order operations so that divisions are done last or not at all.

The bigint you describe is just a poor man's rational, given that no computer architecture or mainstream language support them natively.

Re: 0.30000000000000004

#323

Earlier quoted context omitted.

I develop accounting software for banks, brokerage houses and likes. Currency, taxes, rebates, etc. handling is NEVER done with floating point. Whatever you do with money you need predictable, reproducible results. It is norm that calculations are checked by software at two companies on both sides of transaction. Any discrepancies are alarms, bug reports, unhappy customers. Every significant operation is exactly spec…

> Currency, taxes, rebates, etc. handling is NEVER done with floating point. Nonsense. I’ve seen real banking code at reputable banks that uses floats. > Whatever you do with money you need predictable, reproducible results. Floats aren’t random. They’re perfectly deterministic, predictable and reproducible. If you do the same operation in two places you get the same result.

> Floats aren’t random. They’re perfectly deterministic, predictable and reproducible. If you do the same operation in two places you get the same result.

That's not exactly true in real hardware, or at least it wasn't until ~10 years ago. With the x87 FPU, internal precision was 80 bits, while the x86 registers were at most 64 bits. So, depending on the way the program would transfer data between the CPU and FPU your could get different results. It is very likely that different compilers and different optimization decisions could change the way these operations were implemented, so you would get slight differences between different versions of the software.

There are/were also several global FP flags that could get changed by other programs running on the same CPU/FPU that could impact the result of calculations. So, if you want 100% reproducible FP, you would have to either audit all software running on the same machine to ensure it doesn't touch those flags, or set the flags yourself for every FP calculation in your your program.

Re: 0.30000000000000004

#324

The runner up for length is FORTRAN with: 0.300000000000000000000000000000000039 And the length (but not value) winner is GO with: 0.299999999999999988897769753748434595763683319091796875

Those look like the same length

Huh? The fortran one is 38 characters long with 33 0s after the 3. The go one is 56 characters long with 15 9s after the 2.

Re: 0.30000000000000004

#325
post #314
post #231

Earlier quoted context omitted.

> Performing arithmetic operations against money in floating point is the dangerous part, as error can accumulate beyond an atomic unit. A good example of this is trying to compute the sales tax on $21.15 given a tax rate of 10%. The exact answer would be $2.115, which should round to $2.12. IEEE 64-bit floating point gives 2.1149999999999998, which is hard to get to round to 2.12 without breaking a bunch of other ca…

The trick is that by default rounding happens using banker's rounding. Programming languages use this because this is what CPUs use. When you want to round your way, you need an extra digit and round manually: def tax_f4(amt, rate): tax = round(amt * rate * 1000) return tax // 10 + (tax % 10 > 4)

That works for 10% of $21.15, giving the desired 212.

However, for 10.14% of $21.15, it gives 215, but it should be 214. Another example is 3.5% of $60.70, for which it gives 213 but correct is 212.

Re: 0.30000000000000004

#326

Earlier quoted context omitted.

> Currency, taxes, rebates, etc. handling is NEVER done with floating point. Nonsense. I’ve seen real banking code at reputable banks that uses floats. > Whatever you do with money you need predictable, reproducible results. Floats aren’t random. They’re perfectly deterministic, predictable and reproducible. If you do the same operation in two places you get the same result.

I write real banking code. There is definitely a banking code that uses floats, e.g. valuation of financial instruments. The parent comment talks about software that does transactions and “simpler” calculations, like taxes and fees etc. When people talk about non-determinism of floating point, what they usually mean is non-associativity, that is (x+y)+z may not be exactly equal to x+(y+z).

[deleted]

Re: 0.30000000000000004

#327

Earlier quoted context omitted.

> Currency, taxes, rebates, etc. handling is NEVER done with floating point. Nonsense. I’ve seen real banking code at reputable banks that uses floats. > Whatever you do with money you need predictable, reproducible results. Floats aren’t random. They’re perfectly deterministic, predictable and reproducible. If you do the same operation in two places you get the same result.

> Floats aren’t random. They’re perfectly deterministic, predictable and reproducible. If you do the same operation in two places you get the same result. That's not exactly true in real hardware, or at least it wasn't until ~10 years ago. With the x87 FPU, internal precision was 80 bits, while the x86 registers were at most 64 bits. So, depending on the way the program would transfer data between the CPU and FPU you…

In a language like Java, all these factors are specified and fully deterministic.

Re: 0.30000000000000004

#328

Earlier quoted context omitted.

'Decimal' is a red herring. The number base doesn't matter. (And what are you going to do when you need currency coversions, anyways?) Floats are a digital approximation of real numbers, because computers were originally designed for solving math problems - trigonometry and calculus, that is. For money you want rational numbers, not reals. Unfortunately, computers never got a native rational number type, so you'll ha…

Historically, it's correct-but-too-vague to say computers were for "solving math problems". Historic computer problems should be divided into two types: business problems and scientific/engineering problems. Business problems include things like tabulation and accounting. Programmable digital computers go back at least as far as UNIVAC I, in 1951 (using programmable digital computers for science doesn't go back THAT…

Agree that rational isn't it. But "reproducing the existing quirks" seems like an accurate description. If you want to pay 7% APR on month-end balances, then that's a real-number calculation, but to match what customers expect you need in addition to specify when to round off to cents.

Re: 0.30000000000000004

#329
post #20

The big issue here is what you're going to use your numbers for. If you're going to do a lot of fast floating point operations for something like graphics or neural networks, these errors are fine. Speed is more important than exact accuracy. If you're handling money, or numbers representing some other real, important concern where accuracy matters, most likely any number you intend to show to the user as a number, f…

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…

Money 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.
Post reply on HN