JDK-8190947 : Insufficient arithmetic Behaviour
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 9.0.1
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • Submitted: 2017-11-08
  • Updated: 2022-03-15
  • Resolved: 2017-11-13
Related Reports
Relates :  
Relates :  
Description
A DESCRIPTION OF THE REQUEST :
There is no integral type support in Java SE for integral decimal types.  It previously was the ase in version 1.2 of Java that float and double, along with their object classes Float and Double, inside java.lang.*, defaulted to an accuracy mode of arithmetic, where infinite binary carry underflows and overflows absolutely did not happen.

types float and ouble need to have an accuracy arithmetic mode again, either by default or their own keyword.  Note that the 'strictfp' keyword, to enforce floating point arithmetic mode, continues to remain part of the language.

JUSTIFICATION :
Because the basic arithmetic operators of +, - , * , / and % need to be available.  Because accuracy mode on float and double are required, because using BigDecimal for everything involves too many subsequent round brackets ().() with re inclosing brackets, all at the same time.  (()().(())).().  Because accuracy mode is required for programs that operate from a decimal type.  Because this behaviour is in line with initial expectations.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
//The following should work for
//double primitive and Double classes, in Java 9 and beyond,
//withstanding auto boxing and auto unboxing.

double a = 0.1d;
double b = 0.1d;
double x = a*b;
System.out.println(x);   // 0.01
System.out.println(x == 0.01) //true

//and

float a = 0.1f;
float b = 0.1f;
float x = a*b;
System.out.println(x); //0.01
System.out.println(x==0.01); //true
ACTUAL -
/*
Actual behaviour includes a mixture
of underflow and overflow of internal binary bits,
which are not logically consistant with the arithmetic desired results.
*/

Double a = new Double(0.1);
    
    Double b = new Double(0.1);
    
    Double x = a*b;
    
    out.println(x); // 0.010000000000000002





---------- BEGIN SOURCE ----------
import java.lang.*;
import static java.lang.System.*;

public class Attempt 
{
    public static void main(String ... args) 
    {    
    Double a = new Double(0.1);
    
    Double b = new Double(0.1);
    
    Double x = a*b;
    
    out.println(x);
    
    float one = 0.1f;
    
    float two = 0.1f;
    
    float result = one*two;
    
    out.println(result);
     }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
There are workarounds for this issue, but only to a limited extent,
since there is no java.lang.StrictMath equivalent for 
java.math.BigDecimal and java.math.BigInteger.  If I wish to
do accuracy mode trigonometry, type exponents and type square roots,
via float and double.


Comments
The title of the talk was certainly inspired by the Goldberg paper (and is referenced within). That paper is more academic in its coverage of the same material than the talk. The more recent book "Numerical Computing with IEEE Floating Point Arithmetic" by Michael L. Overton covers floating-point material at a similar level as the talk.
14-11-2017

There is also the following article, "What Every Computer Scientist Should Know About Floating-Point Arithmetic," by David Goldberg, reprinted from ACM Computing Surveys, V23 N1, March 1991. It's available on-line here, by permission: https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html I believe the above-referenced conference presentation is based on this article.
14-11-2017

The semantics of the built-in types int, long, float, and double has been essentially unchanged since the beginning of Java. The strictfp changes in JDK 1.2 did offer a alternative mode of operation, but the computed results were still required to nearly always be the same. Floating-point arithmetic is inherently approximate. Additionally, many decimal values are not exactly representable in binary leading to what-you-see-is-*not*-what-you-get results around decimal <-> binary conversion. Please refer to "What Every Java Programmer Should Know About Floating-Point Arithmetic," https://www.youtube.com/watch?v=fQ_EtTJHKsM or similar floating-point tutorial for more information. For BigDecimal, JDK-4297957: "Add algebraic and transcendental functions operating on BigDecimal" was closed as will not fix. There are no current plans for changing that assessment. Closing this enhancement as will not fix.
13-11-2017