前言
看标题是不是觉得这是一个很简单的问题,我一开始也是这么认为的,但是实际情况下,在各种情况下我们都进行了测试,发现很多实际情况是无法不尽如人意的。
方法分析
当前能想到的比较容易有下面几种
1、直接使用double处理
2、将double转换成String进行处理
方法一:直接对double进行处理,进行计算通过计算后的结果进行取模操作获取小数位数,如下:
public static int getNumberDecimalDigits(double number) { if (number == (long)number) { return 0; } int i = 0; while (true){ i++; if (number * Math.pow(10, i) % 1 == 0) { return i; } } }
方法二:将double转换成String后,然后利用“.”分割进行判断,如下:(这里double转换String有多种方式这里我们选择其中的一种)
public static int getNumberDecimalDigits(double number) { String moneyStr = String.valueOf(number); String[] num = moneyStr.split("\."); if (num.length == 2) { for (;;){ if (num[1].endsWith("0")) { num[1] = num[1].substring(0, num[1].length() - 1); }else { break; } } return num[1].length(); }else { return 0; } }
测试方法:
public static void main(String[] args) { System.out.print(getNumberDecimalDigits(0)); System.out.print(" " + getNumberDecimalDigits(0.0)); System.out.print(" " + getNumberDecimalDigits(1)); System.out.print(" " + getNumberDecimalDigits(-11.1)); System.out.print(" " + getNumberDecimalDigits(1.01)); System.out.print(" " + getNumberDecimalDigits(0.0100)); System.out.print(" " + getNumberDecimalDigits(0.123456)); System.out.print(" " + getNumberDecimalDigits(11111111.1234)); System.out.print(" " + getNumberDecimalDigits(11.0123456789)); }
结果分析
测试结果:
方法一:0 0 0 1 2 2 6 5 11
方法二:0 0 0 1 2 2 6 13 10
为什么最后的结果和我们想象不一样呢???
原因有三个:
1、double计算丢失精度:
2.01 * 10 = 20.099999999999998
2、double转string丢失精度:
String.valueOf(11111111.1234) = 1.11111111234E7
11111111.1234 + "" = 1.11111111234E7
Double.valueOf(11111111.123) = 1.1111111123E7
...
总结
所以在当前情况下,只要使用double进行判断都会出现各种各样的问题,因为double精度的问题。
所以唯一能解决的办法就是,不要使用double,直接使用字符串,无论是从客户端传入的值还是生产的值都是直接使用字符串进行处理和判断,判断方法与方法二类似。
如果非要进行计算,请使用BigDecimal进行计算。new BigDecimal的时候注意一定要使用字符串作为参数进行new
如果你有更好的方法,能通过上面的测试,那赶紧评论让我膜拜膜拜~