Floating Point and Arithmetic Changes for Java SE Lnguage

joe darcy joe.darcy at oracle.com
Wed Mar 7 20:35:51 UTC 2018


Legend has it that after the ancient Greek Hippasus shared with his 
fellow travelers the elegant proof [1] that the square root of 2 is not 
a rational number, he was thrown off the ship by Pythagoreans outraged 
that such numbers should exist. Hippasus subsequently drowned. Whatever 
catharsis was released by his death did not change the fact that 
mathematically sqrt(2) cannot be exactly represented by the ratio of two 
integers.

Rational numbers are simple and elegant. However, in many areas we 
cannot limit ourselves to dealing with rational numbers since values 
like sqrt(2) cannot be accommodated. To greatly abbreviate the 
development of different kinds of numbers, real numbers are commonly 
used, despite their complexities, since they contain their limits, 
meaning that transcendental values like pi are inside the system.

Floating-point arithmetic is a systematic approximation to real 
arithmetic, an approximation with pragmatic compromises to facilitate 
calculation on computers. Floating-point numbers can represent numbers 
over vast scales and are (typically) fixed-sized. These aspects of 
floating-point arithmetic force most field axioms to fail to hold, field 
axioms being the familiar properties of arithmetic such as addition 
being associative ((a+b) + c == a + (b+c)).

Other fixed-size approximations that have been explored, such as 
fixed-slash and floating-slash arithmetic, have been found to have worse 
computational shortcomings than floating-point arithmetic.

It is true that using a binary floating-point representation rather than 
a decimal floating-point representation can cause additional surprises 
since 1/10 is not exactly representable in binary. However, all the 
field axioms that fail to hold for binary floating-point arithmetic also 
fail to hold for decimal floating-point arithmetic. In addition, the 
distances between adjacent decimal numbers makes a larger relative jump 
(ten-fold) across exponent boundaries than for binary (doubling).

The IEEE 754-2008 standard incorporated decimal arithmetic into an 
update of the 1985 version of the standard. This included fixed-size 64 
and 128 bit decimal formats, amenable for hardware support. However, few 
architectures have added such support.

Moreover, the roundoff errors from floating-point computation are only 
one source of errors in a computation. *Even if arithmetic were done 
exactly, numerical analysis would still be needed.* As numerical analyst 
Nick Trefethen has said "If rounding errors vanished, 95% of numerical 
analysis would remain." For example, exact arithmetic does not remove 
modeling error, where the model does have sufficient fidelity with 
reality. Many calculations involve sums of an infinite number of 
decreasing terms so truncation errors occurs for the tail of the total 
sum once the terms are no longer included.

The bugs have you filed and the emails you have sent to this alias are 
all known situations and have all received responses:

     JDK-8190947 -- Insufficient arithmetic Behaviour
     Closed -- will not fix, including citations to additional 
explanations of floating-point.

     JDK-8197995 - BigDecimal and BigInteger Defaulting Behaviour
     Closed -- not an issue, long-existing documentation describes 
exactly how to avoid the reported problem.

     JDK-8190991 - Forward and Inverse operations accuracy.
     Closed -- not an issue. With fixed-precision, it is not possible to 
invert operations over the entire domain,    as previously discussed on 
this list 
http://mail.openjdk.java.net/pipermail/core-libs-dev/2017-December/050393.html.

     JDK-8190946 - There is no elementary functions support for 
BigDecimal and BigInteger.
     Closed as a duplicate of  JDK-4297957, which in turn was created in 
1999 and closed as will not fix in 2006.

Repeatedly ignoring these responses and the reasons given for them will 
not make advancing your cause easier and wastes the time of those 
crafting the replies.

To examine a few of these more closely, for JDK-8190991: "Forward and 
Inverse operations accuracy" the responses give examples where for a 
fixed-precision result, the function cannot be exacted inverted even in 
the case where the true function is monotonically increasing (where it 
is defined), like square root. The concrete example previously sent to 
core libs: sqrt on the domain [1, 2) is in the range [1, ~1.4). From the 
pigeon-hole principle, this cannot be in inverted in the same precision 
since (of necessity) multiple elements of the domain map to the same 
element in the domain. In fact, a majority of elements of range must 
have two or more corresponding domain elements.

For JDK-8190946: "There is no elementary functions support for 
BigDecimal and BigInteger", it is a true observation that BigDecimal and 
BigInteger offer few elementary math functions, many fewer functions 
than are supported for double in java.lang.{Math, StrictMath}. It is 
also true that a larger suite of math library methods for BigDecimal 
would be useful to some users. However, the mere fact that a set of new 
library methods would be useful for some users is *not* sufficient cause 
to have the JDK team work to develop, test, and maintain such a library. 
It is perfectly acceptable and in many ways preferable for limited-use 
libraries to be developed outside of the JDK and not shipped as part of 
the JDK.

One of the use-cases for the value type changes being worked on in 
Project Valhalla is lower-overhead for numerical types, such as 
BigDecimal and BigInteger and potential classes like complex, etc. IMO, 
it would also be reasonable to have syntactic support for operators on 
such types.

There are no prospects for a fundamental redefinition of the 
floating-point semantics of the Java language and VM. It is possible a 
faster and looser mode will be defined at some point, but altering the 
default is extremely unlikely. Long-term, decimal-based arithmetic (and 
other kinds of arithmetic) may get better support as a consequence of 
the features in Valhalla. Filing additional bugs or additional emails to 
this alias will not change any of this or make it happen faster.

A few notes on what this mailing list is and is not. This list and other 
lists under of the OpenJDK umbrella are forums for people participating 
in OpenJDK development and who want to be informed about OpenJDK 
development. These lists are not a free support channel. These lists are 
not a forum to drop in, issue demands for large projects without so much 
as an offer of assistance, and then check back a few months later to see 
why more progress hasn't been made.

-Joe

[1] Assume sqrt(2) is a rational in lowest terms, p/q. Then, by 
definition, 2 = (p^2)/(q^2) and therefor 2(q^2) = p^2. Consequently p^2 
is even which implies p is even as well. Let r = p/2; r is an integer. 
p^2 = (2r)^2 = 4r^2. Substituting, 2(q^2) = 4(r^2), reducing q^2 = 
2(r^2). Therefore, q^2 is even and q is even as well. However, we have 
reached a contradiction. If both p and q are even, then p/q is *not* in 
lowest terms. Therefore, there is no rational number which is the square 
root of 2.


More information about the core-libs-dev mailing list