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