Earlier quoted context omitted.
Decimal floating point won't avoid this issue, for a sufficiently large value the ulp would be 10.
The way to avoid this issue is to avoid floating-point numbers that have any implicit zeroes (due to exponent) after its significant digits. Basically restrict the range to only values where it's guaranteed that for any x1 and x2 from the range, (x1-x2) produces a non-zero dx such that x2+dx == x1. The only example off the top of my head that is floating point is C# "decimal", which actually originates from the Decim…
9999999999999999.0 – 9999999999999998.0
201–210 of 274 posts
Re: 9999999999999999.0 – 9999999999999998.0
#202Earlier quoted context omitted.
Yeah, the limitations of FP are well-known to anyone who does much numerical work. Floating point numbers are the optimal minimum message length method of representing reals with an improper Jeffery's prior distribution. A Jeffery's prior is a prior that is invariant under reparameterization, which is a mandatory property for approximating the reals. In this case, it is where Prob(log(|x|)) is proportional to a const…
Outside of the academic world decimals are almost always a better solution if performance isn't critical. Most logic is multiplicative. For example, apply a 30% tax on a dollar quantity and display both subtotal and grand total. With floats, there are inequalities. With decimal there usually aren't unless you're dividing, but we already have to deal with divide errors in base ten, and it is much more likely to need t…
Is “academic world” now a shorthand for “all numerical computing”?
Decimals basically never make sense, except possibly in some calculations related to money. Those make up a minuscule part of modern computer use.
Maybe decimals are also better for homework assignments for schoolchildren?
The type of applications where decimals are useful are by and large insensitive to compute speed and need no special hardware support. You can easily write your code for decimal arithmetic on top of integer arithmetic hardware.
Those of us who need binary floating point for graphics, audio, games, engineering, science, .... won’t stop you.
Re: 9999999999999999.0 – 9999999999999998.0
#203Earlier quoted context omitted.
> considering the problem is to fit the reals into 64/32/16 bits and have fast math Floating-point numbers (and IEEE-754 in particular) are a good solution to this problem, but is it the right problem? I think the "minimum of surprises" part isn't true. Many programmers develop incorrect mental models when starting to program, and get no feedback to correct them until much later (when they get surprised). It is true…
Showing that the result of 9999999999999999.0 – 9999999999999998.0 is a number between 1.9999999999999998 and 2.0000000000000124 will not solve the problem. IEEE floating point doesn't keep track of loss of precision.
Nevertheless, you have a good point and what I take away from this is that showing a range for the end result of a computation (instead for a given number directly entered by the user/programmer) can be misleading if the result of the exact computation wouldn't actually have been in that range.
Re: 9999999999999999.0 – 9999999999999998.0
#204Re: 9999999999999999.0 – 9999999999999998.0
#205Earlier quoted context omitted.
The correct solution is to understand how floating point number systems work and use near comparisons for floats. Decimal fp is still 'wrong' for, say, 1/3 + 1/3 = 2/3.
A lot of real-world data is already in base-10 for obvious reasons, and so an arrangement that lets you add, subtract and multiply those without worrying is worthwhile, even if it can't handle something more exotic.
Maybe we really should move back to base-60 like the Babylonians used, then you could at least divide by 3.
Re: 9999999999999999.0 – 9999999999999998.0
#206That said, even in Common Lisp I think its only CLISP (among the free implementations) that gives the correct answer for long floats.
CLISP:
[1]> (- 9999999999999999.0L0 9999999999999998.0L0)
1.0L0
SBCL, CMUCL and Clozure CL: * (- 9999999999999999.0L0 9999999999999998.0L0)
2.0d0
The standard only mandates a minimum precision of 50 bits for both double and long floats, so there's no guarantee that using long floats will give the correct answer, as we can see.http://www.lispworks.com/documentation/HyperSpec/Body/t_shor...
Re: 9999999999999999.0 – 9999999999999998.0
#207Earlier quoted context omitted.
How do you mean? The x86-64 instruction set / abi specifies long doubles as 80-bits, and still supports them ...
Essentially there are two different sets of floating point instructions on x86 and x86-64: - the x87 instructions, which descend from the original 8087 coprocessor (and have 80-bit registers), and - the SSE instructions, which descend from the Pentium MMX feature set, are faster, support SIMD operations, and can be fully pipelined. The x87 instructions are basically for legacy compatibility, or if you manually use lo…
(Sorry, this is more for the folks who aren't familiar with this, since it seems like you are familiar, but I didn't want it to seem like this isn't widely supported when they read "legacy" or "some platforms")
Here is a good toy examples that runs into the same numbers shown in the parent, showing the two different instruction types, and that long double can give you the correct answer, while still being run in hardware, vs. going all the way to float128s which are currently emulated in software!
Code w/ Assembly: https://godbolt.org/z/W3ZmqJ Output: https://onlinegdb.com/Sy_I3Q1ME
Re: 9999999999999999.0 – 9999999999999998.0
#208I don't understand all the crap that IEEE 754 gets. I appreciate that it may be surprising that 0.1 + 0.2 != 0.3 at first, or that many people are not educated about floating point, but I don't understand the people who "understand" floating point and continue to criticize it for the 0.1 + 0.2 "problem." The fact is that IEEE 754 is an exceptionally good way to approximate the reals in computers with a minimum number…
Yeah, the limitations of FP are well-known to anyone who does much numerical work. Floating point numbers are the optimal minimum message length method of representing reals with an improper Jeffery's prior distribution. A Jeffery's prior is a prior that is invariant under reparameterization, which is a mandatory property for approximating the reals. In this case, it is where Prob(log(|x|)) is proportional to a const…
Maybe, but that doesn't mean the particular implementation of floats being used is the best one. See also: Unums and Posits
Re: 9999999999999999.0 – 9999999999999998.0
#209There is interesting ongoing research on representing exact reals: https://youtu.be/pMDoNfKXYZg
A specialist number representation is made for exact representation of values in geometric calculations (think CAD). Numbers are represented as sums of rational multiples of cos(iπ/2n).
Exact summation, multiplication and division (not shown) of these quantities are possible, and certain edge-cases (eg. sqrt) have special-case handling.
The system was integrated into and tested on an existing codebase.
The speaker was also one of the authors of Herbie, if other people remember that.
Re: 9999999999999999.0 – 9999999999999998.0
#210But oh well.