简体   繁体   中英

Is there a way to set the Floating-Point Unit's rounding mode in Java?

I want to know how to round a floating-point number to a machine floating number(for example double ). The number "0.01111116" cannot be represented by machine floating point, in some rounding mode, this number should be represented as "0.011111159999999995" with some precision loss. But I don't know how to finish this in Java? So I want to know the API to set the rounding mode to get the exact representation of machine floating-point number in Java. Thanks!

The Java specification does not provide any means to control the floating-point rounding mode. Round-to-nearest is used.

It is not generally possible to arrange for floating-point arithmetic to produce mathematically exact results, so software must be designed to tolerate and adjust for errors or, in very special cases, to get exact results by using extra care.

If you are talking about a literal 0.01111116 in the source code of your program, the Java compiler converts that into the binary floating point representation at compile time.

If you are talking about (say) a String containing the characters "0.01111116", that gets converted to a binary floating point representation if/when you call ( for example ) Double.parseDouble(...) .

Either way, the conversion happens behind the scenes and you don't have any control over the actual rounding. But in a sense it is moot. It is inherent in the nature of the representation that some rounding happens, and the result is generally speaking "the most accurate" you can get from a mathematical perspective ... given the floating point type you have chosen.

If you really wanted the conversion to use different rounding / truncation rules you could either do this after the fact (eg round or truncate the converted value), or you could implement your own String to floating-point conversion method.

You won't be able to change the way that the Java compiler converts literals. It is part of the language specification.


So I want to know the API to set the rounding mode to get the exact representation of machine floating-point number in Java.

There is another way of thinking about this.

The exact representation of a machine floating point number is 32 or 64 bits of binary data. You could render the bits of a double as hexadecimal in a couple of ways:

  • Double::doubleToLongBits or Double::doubleToRawLongBits followed by Long::toHexString gives a precise but unhelpful rendering, or
  • Double::toHexString gives a hexadecimal floating point representation.

All of these renderings are exact (no rounding errors) representations of the double , but most readers won't understand them. (The "raw" version deals best with edge-cases involving variant NaN values.)

There are equivalent methods for float .

Try commons-math3 Precision http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html

    double d = 0.1 + 0.2;
    System.out.println(d);
    d = Precision.round(d, 1);  <-- 1 decimal place
    System.out.println(d);

output

0.30000000000000004
0.3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM