1.java中BigDecimal 的源码加减乘除和“+”“-”“*”“/”有什么区别
2.BigDecimal转换成String的精度问题
3.Java为什么不能使用 BigDecimal 的 equals 方法做等值比较
4.BigDecimal的精度与刻度
5.BigIntegerä¸BigDecimal
java中BigDecimal 的加减乘除和“+”“-”“*”“/”有什么区别
BigDecimal用作商业计算的。BigDecimal aDouble =new BigDecimal(1.); 输出:1.
BigDecimal aString = new BigDecimal("1."); 输出:1.
以上两者输出结果是解析不一样的。
原因:
double的源码构造方法有不可预知性。
String的解析构造方法是固定的值。
所以如果类型是源码Double的话,而且需要精确计算,解析LOL刷人机源码就用下面方法:
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的源码转换中精度丢失。为此,备份 hexo 源码对BigDecimal的精度展示进行了深入研究。
转换方式主要有两种:String.format和price.setScale。首先,采用String.format的原始方法,它依赖于format源码中的fs.print(),尤其printFloat方法,其默认的RoundMode.halfUp策略导致了进位误差。进一步分析,这种模式会自动进行向上取整,造成精度损失。
相比之下,采用price.setScale的方式更具优势。这种方式允许开发者自定义舍入策略,避免了默认进位带来的偏差。在具体实现中,电缆企业源码通过divideAndRound方法,可以灵活控制精度。结合toPlainString方法,可以满足各种精度需求,得到更准确的结果。
总的来说,String.format由于其默认的舍入规则可能导致精度问题,而price.setScale则提供了更多选择,能更好地解决精度转换中的困扰,是更推荐的做法。
Java为什么不能使用 BigDecimal 的 equals 方法做等值比较
前言
在Java编程中,`BigDecimal`是数学包`java.math`提供的一种可以进行精确运算的类型。它在支付、电商等业务中使用广泛,并内置了加、站源码泄漏减、乘、除等运算方法。然而,在使用`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 继æ¿çï¼ä¹æ¯ä¸å¯å对象ã