[英]JAVA floating point operations
我在我的应用程序中做了很多浮点运算,我知道浮点运算不是100%准确,这很好但是在打印结果时我还没有找到一种方法来正确地格式化它。
例如
0.1 + 0.1 = 0.19999999999999999999999
Math.sin(Math.PI)= 1.2246E16而不是0
和1.000000000000000001之类的东西
我正在寻找一种通用的方法来获取这些结果并获得正确的舍入值(以String形式)
所以0.1 + 0.1 = 0.19999999999999999999999 - > 0.2这个需要四舍五入
Math.sin(Math.PI)= 1.2246E16 - > 0
和1.000000000000000001 - > 1之类的东西; 而这个需要四舍五入
我还想避免在结果为1.1234567891234567或1.33333333333333的情况下丢失数据,在这些情况下结果应该保持不变。
使用例如System.out.printf("%.6f", myFloat)
。
如果要避免使用格式化,可以在打印之前将结果舍入为固定精度,并使用Java将执行少量舍入以隐藏表示错误的事实。
例如到小数点后6位
public static double round6(double d) {
return Math.round(d * 1e6) / 1e6;
}
round()
和1e6
的结果可以准确表示。 另外“ IEEE 754需要正确的舍入:也就是说,舍入结果就好像使用无限精确的算术来计算值然后舍入”剩下的唯一错误是表示错误,因为它取最近的可表示值。 Java的toString()假设当你有一个具有最近可表示的较小十进制值的double时,就是你想要看到的。
例如,0.1的实际值是
System.out.println(new BigDecimal(0.1));
版画
0.1000000000000000055511151231257827021181583404541015625
但是当Double.toString()传递给这个值时,它确定0.1将被转换为这个double,所以这就是它应该显示的内容。
BTW在Java 6中,存在一个不使用最小位数的错误。
for (int i = 1; i <= 9; i++)
System.out.print(i / 1000.0 + " ");
在Java 6打印
0.0010 0.0020 0.0030 0.0040 0.0050 0.0060 0.0070 0.0080 0.0090
并在Java 7打印
0.001 0.002 0.003 0.004 0.005 0.006 0.007 0.008 0.009
如果性能不是很关键,我经常使用printf,如果是,我使用自定义例程将double写入直接ByteBuffer到固定精度(有效地舍入它)这样会更快,因为它不会创建任何对象。
我还想避免在结果为1.1234567891234567或1.33333333333333的情况下丢失数据,在这些情况下结果应该保持不变。
在这种情况下,在您需要显示结果之前,请不要对结果进行舍入。
如果要避免丢失小数,请使用BigDecimal而不是float。 更慢但更准确。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.