简体   繁体   English

有没有办法在Java中设置浮点单元的舍入模式?

[英]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 ). 我想知道如何将浮点数四舍五入为机器的浮点数(例如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. 数字“ 0.01111116”不能用机器浮点表示,在某些舍入模式下,该数字应表示为“ 0.011111159999999995”,但有一些精度损失。 But I don't know how to finish this in Java? 但是我不知道如何用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. 所以我想知道API设置舍入模式以获取Java中机器浮点数的确切表示。 Thanks! 谢谢!

The Java specification does not provide any means to control the floating-point rounding mode. Java规范不提供任何控制浮点舍入模式的方法。 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. 如果您要在程序源代码中谈论文字0.01111116 ,则Java编译器会在编译时将其转换为二进制浮点表示形式。

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(...) . 如果您正在谈论(例如)一个包含字符“ 0.01111116”的字符串,则当( 例如 )调用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. 如果您确实希望转换使用不同的舍入/截断规则,则可以在事后执行此操作(例如,舍入或截断转换后的值),或者可以实现自己的String到浮点转换方法。

You won't be able to change the way that the Java compiler converts literals. 您将无法更改Java编译器转换文字的方式。 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. 所以我想知道API设置舍入模式以获取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. 机器浮点数的确切表示形式是32或64位二进制数据。 You could render the bits of a double as hexadecimal in a couple of ways: 您可以通过以下两种方法将double精度位表示为十六进制:

  • Double::doubleToLongBits or Double::doubleToRawLongBits followed by Long::toHexString gives a precise but unhelpful rendering, or Double::doubleToLongBitsDouble::doubleToRawLongBits后跟Long::toHexString提供精确但无用的呈现,或者
  • Double::toHexString gives a hexadecimal floating point representation. Double::toHexString给出十六进制浮点表示形式。

All of these renderings are exact (no rounding errors) representations of the double , but most readers won't understand them. 所有这些渲染图都是double精确表示(没有舍入错误),但是大多数读者不理解它们。 (The "raw" version deals best with edge-cases involving variant NaN values.) (“原始”版本最适合涉及变体NaN值的边缘情况。)

There are equivalent methods for float . 有等效的float方法。

Try commons-math3 Precision http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html 试用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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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