java如何获取一个double的小数位数

前言

看标题是不是觉得这是一个很简单的问题,我一开始也是这么认为的,但是实际情况下,在各种情况下我们都进行了测试,发现很多实际情况是无法不尽如人意的。

方法分析

当前能想到的比较容易有下面几种
1、直接使用double处理
2、将double转换成String进行处理

方法一:直接对double进行处理,进行计算通过计算后的结果进行取模操作获取小数位数,如下:

1public static int getNumberDecimalDigits(double number) { 2 if (number == (long)number) { 3 return 0; 4 } 5 int i = 0; 6 while (true){ 7 i++; 8 if (number * Math.pow(10, i) % 1 == 0) { 9 return i; 10 } 11 } 12 }

方法二:将double转换成String后,然后利用“.”分割进行判断,如下:(这里double转换String有多种方式这里我们选择其中的一种)

1public static int getNumberDecimalDigits(double number) { 2 String moneyStr = String.valueOf(number); 3 String[] num = moneyStr.split("\\."); 4 if (num.length == 2) { 5 for (;;){ 6 if (num[1].endsWith("0")) { 7 num[1] = num[1].substring(0, num[1].length() - 1); 8 }else { 9 break; 10 } 11 } 12 return num[1].length(); 13 }else { 14 return 0; 15 } 16}

测试方法:

1public static void main(String[] args) { 2 System.out.print(getNumberDecimalDigits(0)); 3 System.out.print(" " + getNumberDecimalDigits(0.0)); 4 System.out.print(" " + getNumberDecimalDigits(1)); 5 System.out.print(" " + getNumberDecimalDigits(-11.1)); 6 System.out.print(" " + getNumberDecimalDigits(1.01)); 7 System.out.print(" " + getNumberDecimalDigits(0.0100)); 8 System.out.print(" " + getNumberDecimalDigits(0.123456)); 9 System.out.print(" " + getNumberDecimalDigits(11111111.1234)); 10 System.out.print(" " + getNumberDecimalDigits(11.0123456789)); 11}

结果分析

测试结果:
方法一: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

如果你有更好的方法,能通过上面的测试,那赶紧评论让我膜拜膜拜~

国外问题提出和解决:
https://stackoverflow.com/questions/6264576/number-of-decimal-digits-in-a-double?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

点赞
收藏

评论区

加载中...

相关推荐

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Java日期时间API系列31

  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前

iOS 常用数学函数

Math.h是c的函数库1、三角函数 doublesin(double);正弦 doublecos(double);余弦 doubletan(double);正切2、反三角函数doubleasin(double);结果介于\PI/2,PI/2\ doubleacos(doub

java 大数基本操作

导言:  计算机中数字的表示范围是有一定的限制的,像Java中,常用的数据类型,如int、double等数据类型表示的范围都是有限的,当我们要计算的数字,其位数达到成百上千时,这些数据类型无法满足我们的需求,C语言中我们可以使用数组来储存位数,再对两个数组进行相应的运算;Java中为了处理大整数的运算,提供了一种数据类型:BigInteger,BigDe

单元格自动计算

在我们填报报表时,有的单元格的数据是需要通过自动计算直接获得,但是不是所有的函数都支持填报自动计算,这是为什么呢?报表是纯java的,其函数是后台程序,是在服务器中完成计算的。而填报中的自动计算是在客户端完成的,这个怎么实现呢?实际上是做了一个函数转换,把后台java函数转换成了适合前端计算的js函数。也就是说能够进行填报自动计算的函数有两套代码,java代

java中的包装类

把int类型转换为double的方法需要通过把int类型通过IntegeranewInteger(数字);建立一个对象a,再通过我们学过的对象.方法来把数据的int类型转换为double类型,实现方法为doubleba.doubleValue();数字b就成了double类型了,想通了就不难了ZKJ成本难看

java如何获取一个double的小数位数 - HelloWorld