`
zhoutaomtv
  • 浏览: 11578 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

刚从书上学到的一个小点:Java中的精确计算

    博客分类:
  • java
阅读更多
一直以来都没有机会做非常需要精确计算的项目,所以对常用的浮点数计算没什么经验。刚看书时发现一个有趣的现象,特写出来与大家分享,可能有些高手会觉得小儿科,但我希望不知道的朋友多注意下。

demo1:
public static void demo1() {
		double a = 1.01;
		double b = 2.01;
		System.out.println(a + b);
		System.out.println();
}

大家运行出来結果应该是3.0199999999999996,而不是3.02.其实代码都没错,只是计算机存储浮点数时是用二进制的,所有的数都保存为以2的N次方。0.5很好表示(2的-1次方),但0.1就没那么好精确了。

有兴趣的朋友可以看一下1.01, 2.01,1.01+2.01,  3.02 的二进制表示有什么区别,你会发现3.02和1.01+2.01的最后一个bit不同。

说了这么多怎么解决精确计算呢?其实java为我们提供了Decimal类与BigDecimal类就是来解决精确计算的,当然精确计算肯定会相对计算慢一些,但如果你要精确计算,你自己权衡一下是要精确还是要性能。

demo2:
public static void demo2() {
		double area;
		for (int i = 1; i < 10; i++) {
			area = 3.14 * i * i;
			System.out.println("圆的半径为" + i + ", 其面积为" + area);
		}
		System.out.println();
}

其实結果为
圆的半径为1, 其面积为3.14
圆的半径为2, 其面积为12.56
圆的半径为3, 其面积为28.259999999999998
圆的半径为4, 其面积为50.24
圆的半径为5, 其面积为78.5
圆的半径为6, 其面积为113.03999999999999
圆的半径为7, 其面积为153.86
圆的半径为8, 其面积为200.96
圆的半径为9, 其面积为254.34


现在我们把输出結果的地方加DecimalFormat类格式化一下。
demo 3:
public static void demo3() {
		double area;
		DecimalFormat df = new DecimalFormat("#.000");
		for (int i = 1; i < 10; i++) {
			area = 3.14 * i * i;
			System.out.println("圆的半径为" + i + ", 其面积为" + df.format(area));
		}
		System.out.println();
}

输出結果为:
圆的半径为1, 其面积为3.140
圆的半径为2, 其面积为12.560
圆的半径为3, 其面积为28.260
圆的半径为4, 其面积为50.240
圆的半径为5, 其面积为78.500
圆的半径为6, 其面积为113.040
圆的半径为7, 其面积为153.860
圆的半径为8, 其面积为200.960
圆的半径为9, 其面积为254.340


結果似乎正确了,其实还没有,请看下一个。
demo4:
public static void demo4() {
		double area = 24.205;
		DecimalFormat df = new DecimalFormat("#.00");
		System.out.println(df.format(area));
		System.out.println();
}

输出結果为:24.20,不是24.21。

要想得到24.21的精确結果,推荐使用BigDecimal提供更大的或更小的数进行运算。
demo5:
public static void demo5() {
		double area = 24.205;
		BigDecimal bd = new BigDecimal(Double.toString(area));
		bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
		System.out.println(bd.doubleValue());
		System.out.println();
}

这样就对了。

看到资料上说BigDecimal推荐使用String类型来初始化构造函数,这样可以避免一些莫名其妙的异常错误。具体原因也提供了一些例子,我这里就不写了。

现在不知道在开源包中有没有进行精确计算的工具,要是哪位朋友知道有的话告诉其他朋友一下。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics