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

Wesley13
• 阅读 582

前言

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

方法分析

当前能想到的比较容易有下面几种
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

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

国外问题提出和解决:
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

点赞
收藏
评论区
推荐文章
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
iOS 常用数学函数
Math.h是c的函数库1、三角函数 doublesin(double);正弦 doublecos(double);余弦 doubletan(double);正切2、反三角函数doubleasin(double);结果介于\PI/2,PI/2\ doubleacos(doub
Wesley13 Wesley13
3年前
java 大数基本操作
导言:  计算机中数字的表示范围是有一定的限制的,像Java中,常用的数据类型,如int、double等数据类型表示的范围都是有限的,当我们要计算的数字,其位数达到成百上千时,这些数据类型无法满足我们的需求,C语言中我们可以使用数组来储存位数,再对两个数组进行相应的运算;Java中为了处理大整数的运算,提供了一种数据类型:BigInteger,BigDe
Wesley13 Wesley13
3年前
java中的包装类
把int类型转换为double的方法需要通过把int类型通过IntegeranewInteger(数字);建立一个对象a,再通过我们学过的对象.方法来把数据的int类型转换为double类型,实现方法为doubleba.doubleValue();数字b就成了double类型了,想通了就不难了ZKJ成本难看
单元格自动计算
在我们填报报表时,有的单元格的数据是需要通过自动计算直接获得,但是不是所有的函数都支持填报自动计算,这是为什么呢?报表是纯java的,其函数是后台程序,是在服务器中完成计算的。而填报中的自动计算是在客户端完成的,这个怎么实现呢?实际上是做了一个函数转换,把后台java函数转换成了适合前端计算的js函数。也就是说能够进行填报自动计算的函数有两套代码,java代
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Wesley13 Wesley13
3年前
MySQL基础数据类型
一介绍  存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的1.数字:整型:tinyinitintbigint小数:float:在位数比较短的情况下不精准double:在位数比较
Wesley13 Wesley13
3年前
Java核心技术卷1 重读经典小记
Java基础java中的int类型固定为32位三个特殊的浮点值:正无穷大(\Double.POSITIVE\_INFINITY\),负无穷大(\Double.NEGATIVE\_INFINITY\)和NaN(\Double.NaN\)。!Java核心技术卷11温故而知新(http
Wesley13 Wesley13
3年前
Java删除空字符:Java8 & Java11
操作字符串是编程时经常遇到的,常用的比如在字符串中处理空格。到目前为止,Java提供了很多从字符串中删除空格的不同方法,即trim,replaceAll。但是,Java11通过诸如strip,stripLeading和stripTrailing之类的方法对这些方法进行了一些功能性的拓展。在大多数情况下,我们只使用trim(
Stella981 Stella981
3年前
How to convert BigDecimal to Double in spring
问题描述:我们都知道对于涉及钱的数据必须使用BigDecimal类型进行存储,今天在查询mongo时仍然有精度问题,虽然我在代码中使用了BigDecimal类型,但mongo中使用的是double类型。我初步推断是mongoTemplate在类型转换时出现了问题,根源还是因为mongodb中使用了double类型来存储。但是我决定不了mongodb于是我只