Earlier quoted context omitted.
Yes, but the Julia REPL produces 2.0 as an answer and casting both these to BigInt doesn't work either.
Thus my second paragraph. You have to opt in to use other formats. Casting to bigint doesn't work because the problem occurs when converting the decimal constant in the source to floating point. You would have to convince the parser to parse the constant as something besides a float.
9999999999999999.0 – 9999999999999998.0
261–270 of 274 posts
Re: 9999999999999999.0 – 9999999999999998.0
#262Are there any mainstream languages that consider a decimal number to be a primitive type? I feel like floating point numbers are far less meaningful in every day programs. Even 2d graphics would be easier with decimal numbers. Unless you're using numbers that scale from very small to very large, like 3d games or scientific calculations, you don't actually want to use floating point.
Re: 9999999999999999.0 – 9999999999999998.0
#263Earlier quoted context omitted.
My CS course at a community college went over the limitations of floats in detail, in the CS class.
How detailed, if I may ask?
Re: 9999999999999999.0 – 9999999999999998.0
#264Earlier quoted context omitted.
You cannot do anything in finance with such reasoning. Take something simple, say a mortgage at 5% compounded 12 times a year. To compute payments using some fixed length representation or decimal is going to lead to more error than to use the usual floating point. This rabbit hole would continue for many applications. Floating point makes them all much easier to do well.
Have you worked on finance software? I have - we always used ints for everything, so we could avoid rounding suprises
How did you use ints to compute compounded interest on loans? I asked that above, and you avoided it. I ask again.
For example, suppose you have a mortgage where you lent $100K at 5% annual, compounded 12 times a year, for 30 years, and you need basic values regarding this loan.
Often in such calculations you need to compute 100K*(1+0.05/12)^360. How do you do that with integers? Naively you need (1+(1/20)/12)^360, which as a reduced fraction each of the numerator and denominator have over 2800 binary digits. Do you really do this with integers?
Now put that in a mortgage trading or pricing system where it needs to do millions/billions of those per second.
Doing this as double gives enough precision to make the difference between computed and infinitely precise negligible (approx. 10^-17 error).
It's easy to make examples where doing incremental calculations, rounding to pennies and storing, results in long term error. In these cases I don't see how do to it with integers without massive overhead.
And this is a trivial, common example. Doing stuff like hedge fund stuff, or anything using numerical integration to make models for pricing, would be astounding hardly to do with integer only math.
What finance software did you write? A simple ledger works fine as integers. Anything more complex will hit performance and scaling issues soon after the basics.
Re: 9999999999999999.0 – 9999999999999998.0
#265Actually Wolfram|Alpha does give 1, but Mathematica 11.3 gives 2.
In this case,
9999999999999999.0`17-9999999999999998.0`17 does indeed return 1.
Re: 9999999999999999.0 – 9999999999999998.0
#266Earlier quoted context omitted.
How do you mean? The x86-64 instruction set / abi specifies long doubles as 80-bits, and still supports them ...
The x87 ISA does, yes, and they are supported for binary compatibility reasons. However the actual x87 registers are shadowed by the vector registers so you can only use one. Any modern vectorizing compiler uses the vector instructions for FPU arithmetic, even when scalar, with a max precision of 64-bit.
Well x86-64 is not binary compatible with x86 so that's not the reason. It is mostly for software relying on either the rounding quirks or the extended 80 bit precision I guess.
> However the actual x87 registers are shadowed by the vector registers so you can only use one
You are confusing with the legacy MMX registers which are deader than the x87 for stack. XMM registers do not shadow the for stack.
Re: 9999999999999999.0 – 9999999999999998.0
#267Earlier quoted context omitted.
> Outside of the academic world decimals are almost always a better solution 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 ar…
Even with money I use integers. Instead of dollars (or local currency), I store values internally as pennies (or local equivalent 1/100 of main currency). Sometimes when working with interest I'll need to work with floats, and some databases I have values stored as DECIMAL(8,2) instead of INT, but for the most part I've saved quite a few headaches by keeping my values in INTs.
Re: 9999999999999999.0 – 9999999999999998.0
#268Earlier quoted context omitted.
Not really. It's used for over 30 years successfully in all lisps. gmp is not really slow, and for limited precision (2k) there exist even faster libs.
gmp is not exact. It's just arbitrary-precision. There's a very large difference. Exact arithmetic handles numbers like pi with infinite precision. When you use gmp, you pre-select select a constant for pi with a precision known ahead of time. In the real world, 64 bits of pi is more than enough for almost every purpose, so whatever. It's fine. But there's a huge conceptual gap between that and exact arithmetic.
Lisp is of course better, optimizing expressions symbolically as far as possible, eg. to rationals, and using bignum and bigint's internally. As exact as possible. perl6 does it too, just 100x slower.
Re: 9999999999999999.0 – 9999999999999998.0
#269Earlier quoted context omitted.
I believe IEEE754 floats have that subtraction/addition guarantee (as long as the hardware doesn't map subnormals to zero). The problem in this case is the input numbers are rounded when they are converted from text/decimal to a float, and so aren't exact.
> I believe IEEE754 floats have that subtraction/addition guarantee (as long as the hardware doesn't map subnormals to zero). They don't - all 11 bits of the exponent (for float64) are in use, so you can have something like 1e300, and then you can't e.g. add 1 to it and get a different number. >>> x = 1e100 >>> x 1e+100 >>> y = x + 1 >>> y 1e+100 >>> x - y 0.0
if x != y, x - y != 0
which holds for all x and y, but is different to if dx != 0, x + dx != x
which fails for some (many!) x and dx.Re: 9999999999999999.0 – 9999999999999998.0
#270I 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…
To me the only downside of IEEE 754 is that most languages including C and C++ do not provide a sensible canonical comparison methods. This leads to surprised beginners and then a ton of home made solutions which are often not appropriate.