简体   繁体   English

JAVA浮点运算

[英]JAVA floating point operations

I'm doing a lot of floating point operations in my application, and I'm aware that floating point operations are not 100% accurate which is fine but when it comes to printing the result I have yet to find a way to format it properly. 我在我的应用程序中做了很多浮点运算,我知道浮点运算不是100%准确,这很好但是在打印结果时我还没有找到一种方法来正确地格式化它。

for example 例如

0.1 + 0.1 = 0.19999999999999999999999 0.1 + 0.1 = 0.19999999999999999999999

Math.sin(Math.PI) = 1.2246E16 instead of 0 Math.sin(Math.PI)= 1.2246E16而不是0

and stuff like 1.000000000000000001 和1.000000000000000001之类的东西

I'm looking for a general way to take those results and get the proper rounded value (in a String form) 我正在寻找一种通用的方法来获取这些结果并获得正确的舍入值(以String形式)

so that 0.1 + 0.1 = 0.19999999999999999999999 -> 0.2 this one requires rounding up 所以0.1 + 0.1 = 0.19999999999999999999999 - > 0.2这个需要四舍五入

Math.sin(Math.PI) = 1.2246E16 -> 0 Math.sin(Math.PI)= 1.2246E16 - > 0

and stuff like 1.000000000000000001 -> 1 ; 和1.000000000000000001 - > 1之类的东西; while this one requires rounding down 而这个需要四舍五入

I'd also like to avoid losing data in cases like when the result is 1.1234567891234567 or 1.33333333333333 in those cases the result should remain the same. 我还想避免在结果为1.1234567891234567或1.33333333333333的情况下丢失数据,在这些情况下结果应该保持不变。

使用例如System.out.printf("%.6f", myFloat)

If you want to avoid using formatting, you can round the result to a fixed precision before printing it and use the fact that Java will do a small amount of rounding to hide representation error. 如果要避免使用格式化,可以在打印之前将结果舍入为固定精度,并使用Java将执行少量舍入以隐藏表示错误的事实。

eg To 6 decimal places 例如到小数点后6位

public static double round6(double d) {
    return Math.round(d * 1e6) / 1e6;
}

The result of round() and 1e6 can be represented exactly. round()1e6的结果可以准确表示。 Additionally " IEEE 754 requires correct rounding: that is, the rounded result is as if infinitely precise arithmetic was used to compute the value and then rounded" The only error left is the representation error as it takes the nearest representable value. 另外“ IEEE 754需要正确的舍入:也就是说,舍入结果就好像使用无限精确的算术来计算值然后舍入”剩下的唯一错误是表示错误,因为它取最近的可表示值。 Java's toString() assumes that when you have a double which has a nearest representable value of a shorter decimal, that is what you want to see. Java的toString()假设当你有一个具有最近可表示的较小十进制值的double时,就是你想要看到的。

eg The actual value for 0.1 is 例如,0.1的实际值是

System.out.println(new BigDecimal(0.1));

prints 版画

0.1000000000000000055511151231257827021181583404541015625

but when Double.toString() is passed this value, it determines that 0.1 would be converted to this double and so this is what it should be displayed. 但是当Double.toString()传递给这个值时,它确定0.1将被转换为这个double,所以这就是它应该显示的内容。

BTW In Java 6 there is a bug where it doesn't use the minimum number of digits. BTW在Java 6中,存在一个不使用最小位数的错误。

for (int i = 1; i <= 9; i++)
    System.out.print(i / 1000.0 + " ");

in Java 6 prints 在Java 6打印

0.0010 0.0020 0.0030 0.0040 0.0050 0.0060 0.0070 0.0080 0.0090

and in Java 7 prints 并在Java 7打印

0.001 0.002 0.003 0.004 0.005 0.006 0.007 0.008 0.009

I often use printf if performance is not critical and if it is, I use a custom routine to write the double to a direct ByteBuffer to a fixed precision (effectively rounding it) This is faster as it doesn't create any objects. 如果性能不是很关键,我经常使用printf,如果是,我使用自定义例程将double写入直接ByteBuffer到固定精度(有效地舍入它)这样会更快,因为它不会创建任何对象。

I'd also like to avoid losing data in cases like when the result is 1.1234567891234567 or 1.33333333333333 in those cases the result should remain the same. 我还想避免在结果为1.1234567891234567或1.33333333333333的情况下丢失数据,在这些情况下结果应该保持不变。

In that case, don't round the results until you need to display them. 在这种情况下,在您需要显示结果之前,请不要对结果进行舍入。

If you want to avoid losing decimals, use BigDecimal instead of float. 如果要避免丢失小数,请使用BigDecimal而不是float。 Slower but more accurate . 更慢但更准确。

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

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