皮皮网

【anager源码详解】【如果查看网站源码】【临床研究ctms源码】bigdecimal源码解析

2024-12-29 02:00:24 来源:项目源码文件

1.java中BigDecimal 的源码加减乘除和“+”“-”“*”“/”有什么区别
2.BigDecimal转换成String的精度问题
3.Java为什么不能使用 BigDecimal 的 equals 方法做等值比较
4.BigDecimal的精度与刻度
5.BigInteger与BigDecimal

bigdecimal源码解析

java中BigDecimal 的加减乘除和“+”“-”“*”“/”有什么区别

       BigDecimal用作商业计算的。

       BigDecimal aDouble =new BigDecimal(1.);     输出:1.

       BigDecimal aString = new BigDecimal("1.");   输出:1.

       以上两者输出结果是解析不一样的。

       原因:

       double的源码构造方法有不可预知性。

       String的解析构造方法是固定的值。

       所以如果类型是源码Double的话,而且需要精确计算,解析anager源码详解就用下面方法:

       Double.toString(double)方法,源码可以先转为String,解析然后再用new BigDecimal("")构造方法。源码

       注意:BigDecimal都是解析不可变的(immutable)的,在进行每一步运算时,源码都会产生一个新的解析对象,所以在做加减乘除运算时千万要保存操作后的源码值

       Demo测试

    public static final void main(String[] args) {

               BigDecimal aBigDecimal = new BigDecimal("1.1");

               BigDecimal bBigDecimal = new BigDecimal("2.0");

               

               BigDecimal subtract = bBigDecimal.subtract(aBigDecimal);

               System.out.println("使用BigDecimal进行相减计算:" + subtract.doubleValue());

               System.out.println("直接相减: " + (2.0 - 1.1));

       结果:

使用BigDecimal进行相减计算:0.9

       直接相减: 0.

BigDecimal转换成String的精度问题

       在项目中遇到一个价格展示问题,.的解析商品在购物车中显示为.,源于BigDecimal到String的源码转换中精度丢失。为此,如果查看网站源码对BigDecimal的精度展示进行了深入研究。

       转换方式主要有两种:String.format和price.setScale。首先,采用String.format的原始方法,它依赖于format源码中的fs.print(),尤其printFloat方法,其默认的RoundMode.halfUp策略导致了进位误差。进一步分析,这种模式会自动进行向上取整,造成精度损失。

       相比之下,采用price.setScale的方式更具优势。这种方式允许开发者自定义舍入策略,避免了默认进位带来的偏差。在具体实现中,临床研究ctms源码通过divideAndRound方法,可以灵活控制精度。结合toPlainString方法,可以满足各种精度需求,得到更准确的结果。

       总的来说,String.format由于其默认的舍入规则可能导致精度问题,而price.setScale则提供了更多选择,能更好地解决精度转换中的困扰,是更推荐的做法。

Java为什么不能使用 BigDecimal 的 equals 方法做等值比较

       前言

       在Java编程中,`BigDecimal`是数学包`java.math`提供的一种可以进行精确运算的类型。它在支付、电商等业务中使用广泛,并内置了加、音效助手i源码减、乘、除等运算方法。然而,在使用`BigDecimal`进行数值比较时,`equals`方法的使用常常引发疑惑。本文将深入探讨为什么不能直接使用`equals`方法进行等值比较,并解释背后的原理。

       等值比较的问题

       根据《阿里巴巴Java开发手册》中的要求,直接使用`==`进行`BigDecimal`对象比较是不正确的。直接使用`equals`方法进行等值判断呢?让我们通过代码运行来验证。

       使用`equals`方法比较`BigDecimal`时,结果会根据值和标度的不同而变化。在某些情况下,使用`int`、阿我巴巴源码`double`定义的`BigDecimal`进行`equals`比较会得到正确的结果,而使用`String`定义的`BigDecimal`则不会。这背后的原因在于`equals`方法不仅比较值,还会比较标度。

       理解`equals`方法内部逻辑

       `equals`方法的源码揭示了其比较逻辑。它不仅比较两个`BigDecimal`对象的值,还会比较它们的标度。因此,即便两个`BigDecimal`对象的值相同,如果它们的标度不同,`equals`方法也会返回`false`。

       代码调试揭示标度差异

       通过代码调试,我们可以看到`bigDecimal5`和`bigDecimal6`的值相同,但标度不同。`bigDecimal5`的标度为0,而`bigDecimal6`的标度为1,导致它们的比较结果为`false`。

       标度差异的来源

       `BigDecimal`的构造方法揭示了标度差异的成因。`BigDecimal`有四种构造方法,其中`BigDecimal(int)`和`BigDecimal(long)`构造的`BigDecimal`对象的标度为0。当使用`BigDecimal(double)`构造方法时,如`new BigDecimal(0.1)`,实际上创建的`BigDecimal`对象的值更精确,因此标度较高。通过调试发现,`new BigDecimal(0.1)`的标度值为。同样地,`new BigDecimal(1.0)`和`new BigDecimal(1.)`形式的`BigDecimal`对象,虽然包含更多数字位,但它们本质上是整数,标度仍为0。

       使用`compareTo`方法进行值比较

       `compareTo`方法提供了只比较两个`BigDecimal`对象值的功能,不考虑标度。在比较`bigDecimal5`和`bigDecimal6`时,使用`compareTo`方法后得到的结果为0,表明这两个`BigDecimal`对象的值相等。

       总结

       总之,当使用`BigDecimal`进行等值比较时,应避免直接使用`equals`方法,而应使用`compareTo`方法进行值比较。这样可以准确地判断两个`BigDecimal`对象是否相等,避免因标度差异造成的混淆。

BigDecimal的精度与刻度

       BigDecimal在处理高精度运算时,能有效避免Double类型的精度损失问题,尤其在金融计算等领域尤为重要。了解BigDecimal的精度与刻度概念对于正确使用这个类至关重要。精度指最多可表示的数字位数,而刻度指小数点后能保留的位数。

       例如,DECIMAL(7, 2) 表示最多可存储7位数字,其中2位为小数点后,5位为整数部分。在BigDecimal中,精度和刻度可通过相关方法获取。

       执行除法运算时,需要指定刻度以控制保留的小数位数,并选择进位模式。模式包括UP、DOWN、CEILING、FLOOR、HALF_UP、HALF_DOWN、HALF_EVEN 和 UNNECESSARY。不指定刻度时,结果能除尽则正常处理,否则会抛出异常。源码中的计算逻辑旨在确保结果的精度。

       使用字符串构造BigDecimal是最佳实践,避免因直接使用数值导致的精度损失。尝试构造一个刻度为的BigDecimal时,结果出乎意料,这是由于二进制无法精确表示某些十进制数,尤其是那些在二进制中有无限循环小数位的数。

       例如,0.1和0.2在二进制中无法精确表示,转换后会变成无限循环小数。由于计算机存储空间有限,这些小数只能被截断,导致精度损失。直接使用Double构造BigDecimal与使用字符串构造的实现不同,原因在于避免直接使用数值时可能出现的精度问题。

BigInteger与BigDecimal

       BigInteger - 廖雪峰的网站

        在Java中,由CPU原生提供的整型最大范围是位 long 型整数。使用 long 型整数可以直接通过CPU指令进行计算,速度非常快。

        如果我们使用的整数范围超过了 long 型怎么办?这个时候,就只能用软件来模拟一个大整数。 java.math.BigInteger 就是用来表示任意大小的整数。 BigInteger 内部用一个 int[] 数组来模拟一个非常大的整数:

        对 BigInteger 做运算的时候,只能使用实例方法,例如,加法运算:

        和 long 型整数运算比, BigInteger 不会有范围限制,但缺点是速度比较慢。

        也可以把 BigInteger 转换成 long 型:

        使用 longValueExact() 方法时,如果超出了 long 型的范围,会抛出 ArithmeticException 。

        BigInteger 和 Integer 、 Long 一样,也是不可变类,并且也继承自 Number 类。因为 Number 定义了转换为基本类型的几个方法:

        因此,通过上述方法,可以把 BigInteger 转换成基本类型。如果 BigInteger 表示的范围超过了基本类型的范围,转换时将丢失高位信息,即结果不一定是准确的。如果需要准确地转换成基本类型,可以使用 intValueExact() 、 longValueExact() 等方法,在转换时如果超出范围,将直接抛出 ArithmeticException 异常。

        如果 BigInteger 的值甚至超过了 float 的最大范围,那么返回的 float 是什么呢?

        和 BigInteger 类似, BigDecimal 可以表示一个任意大小且精度完全准确的浮点数。

        通过 BigDecimal 的 stripTrailingZeros() 方法,可以将一个 BigDecimal 格式化为一个相等的,但去掉了末尾0的 BigDecimal :

        如果一个 BigDecimal 的 scale() 返回负数,例如, -2 ,表示这个数是个整数,并且末尾有2个0。

        可以对一个 BigDecimal 设置它的 scale ,如果精度比原始值低,那么按照指定的方法进行四舍五入或者直接截断:

        对 BigDecimal 做加、减、乘时,精度不会丢失,但是做除法时,存在无法除尽的情况,这时,就必须指定精度以及如何进行截断:

        还可以对 BigDecimal 做除法的同时求余数:

        调用 divideAndRemainder() 方法时,返回的数组包含两个 BigDecimal ,分别是商和余数,其中商总是整数,余数不会大于除数。我们可以利用这个方法判断两个 BigDecimal 是否是整数倍数:

        在比较两个 BigDecimal 的值是否相等时,要特别注意,使用 equals() 方法不但要求两个 BigDecimal 的值相等,还要求它们的 scale() 相等:

        必须使用 compareTo() 方法来比较,它根据两个值的大小分别返回负数、正数和0,分别表示小于、大于和等于。

        总是使用 compareTo() 比较两个 BigDecimal 的值,不要使用 equals() !

        如果查看 BigDecimal 的源码,可以发现,实际上一个 BigDecimal 是通过一个 BigInteger 和一个 scale 来表示的,即 BigInteger 表示一个完整的整数,而 scale 表示小数位数:

        BigDecimal 也是从 Number 继承的,也是不可变对象。