Java Bigdecimal使用原理詳解
一般來說,一提到Java里面的商業(yè)計(jì)算,我們都知道不能用float和double,因?yàn)樗麄儫o法進(jìn)行精確計(jì)算。但是Java的設(shè)計(jì)者給編程人員提供了一個(gè)很有用的類BigDecimal,他可以完善float和double類無法進(jìn)行精確計(jì)算的缺憾。
BigDecimal類位于java.maths類包下。首先我們來看下如何構(gòu)造一個(gè)BigDecimal對(duì)象。它的構(gòu)造函數(shù)很多,這里挑選最常用的兩個(gè)來演示一下:一個(gè)就是BigDecimal(double val),另一個(gè)就是BigDecimal(String str)。這兩個(gè)看上去沒什么太大區(qū)別,但是正像API描述中說:
/*The results of this constructor can be somewhat unpredictable. One might assume that new BigDecimal(.1) is exactly equal to .1, but it is actually equal to .1000000000000000055511151231257827021181583404541015625. This is so because .1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the long value that is being passed in to the constructor is not exactly equal to .1, appearances nonwithstanding.The (String) constructor, on the other hand, is perfectly predictable: new BigDecimal('.1') is exactly equal to .1, as one would expect. Therefore, it is generally recommended that the (String) constructor be used in preference to this one.*/
也就是說利用double作為參數(shù)的構(gòu)造函數(shù),無法精確構(gòu)造一個(gè)BigDecimal對(duì)象,需要自己指定一個(gè)上下文的環(huán)境,也就是指定精確位。而利用String對(duì)象作為參數(shù)傳入的構(gòu)造函數(shù)能精確的構(gòu)造出一個(gè)BigDecimal對(duì)象。請(qǐng)看下面的代碼:
import java.math.*;public class TestBigDecimal { public static void main(String args[]){ BigDecimal bd = new BigDecimal( '10.123'); BigDecimal bd1 = new BigDecimal(10.123); System.out.println(bd +'/n'+ bd1); }}運(yùn)行后輸出:10.12310.1229999999999993320898283855058252811431884765625
所以我們?cè)谶x擇構(gòu)造函數(shù)時(shí),要看具體需求而定。
另外,很多人會(huì)問到怎么將基本類型,如int,float,double,long,和BigDecimal對(duì)象相互轉(zhuǎn)換。很簡(jiǎn)單:
基本類型通過構(gòu)造函數(shù)轉(zhuǎn)換成對(duì)應(yīng)的BigDecimal對(duì)象,而BigDecimal類提供了諸如intValue(), floatValue(), doubleValue(), longValue()方法來將BigDecimal對(duì)象轉(zhuǎn)換成對(duì)應(yīng)的值。
一、BigDecimal 的加減乘除
BigDecimal bignum1 = new BigDecimal('10'); BigDecimal bignum2 = new BigDecimal('5'); BigDecimal bignum3 = null; //加法 bignum3 = bignum1.add(bignum2); System.out.println('和 是:' + bignum3); //減法 bignum3 = bignum1.subtract(bignum2); System.out.println('差 是:' + bignum3); //乘法 bignum3 = bignum1.multiply(bignum2); System.out.println('積 是:' + bignum3); //除法 bignum3 = bignum1.divide(bignum2); System.out.println('商 是:' + bignum3);
二、BigDecimal 的比較大小。
BigDecimal num1 = new BigDecimal('0'); BigDecimal num2 = new BigDecimal('1'); BigDecimal num3 = new BigDecimal('2'); BigDecimal num = new BigDecimal('1'); //用做比較的值 System.out.println(num1.compareTo(num)); //小于 時(shí),返回 -1 System.out.println(num2.compareTo(num)); //等于 時(shí),返回 0 System.out.println(num3.compareTo(num)); //大于 時(shí),返回 1
補(bǔ)充:
BigInteger 也可以存放比較大的數(shù), 和 BigDecimal 的區(qū)別是 :BigInteger 存放的是大的整數(shù),而BigDecimal 存放大的小數(shù)
繼續(xù)補(bǔ)充一下,用BigDecimal 寫個(gè)for循環(huán)。
for (BigDecimal i = new BigDecimal('0'); i.compareTo(new BigDecimal('10')) != 1; i = i.add(new BigDecimal('1'))) { System.out.print(i + 't'); }
控制臺(tái)打印的是從0 到 10 。
三、Java中的BigDecimal使用注意事項(xiàng)
1.BigDecial是immutable的,就像String一樣,它的所有操作都會(huì)生成一個(gè)新的對(duì)象,所以
amount.add( thisAmount );
是錯(cuò)誤的;而應(yīng)該是:
amount = amount.add( thisAmount );
2. 不要用equals方法來比較BigDecimal對(duì)象,因?yàn)樗膃quals方法會(huì)比較scale,如果scale不一樣,它會(huì)返回false;
BigDecimal a = new BigDecimal('2.00');BigDecimal b = new BigDecimal('2.0');print(a.equals(b)); // false
所以你應(yīng)該使用compareTo()和signum()方法
a.compareTo(b); // returns (-1 if a < b), (0 if a == b), (1 if a > b)a.signum(); // returns (-1 if a < 0), (0 if a == 0), (1 if a > 0)
3. 使用BigDecimal的字符串構(gòu)造函數(shù),不要使用double參數(shù)的構(gòu)造函數(shù),否則的話會(huì)出現(xiàn)你不想要的結(jié)果。
例如下面的代碼分別使用double和String的構(gòu)造函數(shù),然后使用HALF_EVEN的round方法,但是輸出結(jié)果不一樣
System.out.println('=================='); for(int i = 0; i < 10; i ++) { StringBuffer sb = new StringBuffer(); sb.append('0.'); sb.append(i); sb.append('5'); BigDecimal bdx = new BigDecimal(sb.toString()); System.out.println(sb + ' ' +bdx.setScale(1, RoundingMode.HALF_EVEN)); } System.out.println('=================='); for(int i = 0; i < 10; i ++) { StringBuffer sb = new StringBuffer(); sb.append('0.'); sb.append(i); sb.append('5'); BigDecimal bdx = new BigDecimal(Double.valueOf(sb.toString())); System.out.println(sb + ' ' +bdx.setScale(1, RoundingMode.HALF_EVEN)); }
輸出是:
==================0.05 0.00.15 0.20.25 0.20.35 0.40.45 0.40.55 0.60.65 0.60.75 0.80.85 0.80.95 1.0==================0.05 0.10.15 0.10.25 0.20.35 0.30.45 0.50.55 0.60.65 0.70.75 0.80.85 0.80.95 0.9
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. SSM框架整合JSP中集成easyui前端ui項(xiàng)目開發(fā)示例詳解2. asp文件用什么軟件編輯3. 每日六道java新手入門面試題,通往自由的道路第二天4. 微信開發(fā) 網(wǎng)頁授權(quán)獲取用戶基本信息5. React中使用TS完成父組件調(diào)用子組件的操作方法6. android Web跳轉(zhuǎn)到app指定頁面并傳遞參數(shù)實(shí)例7. python中的class_static的@classmethod的巧妙用法8. PHP session反序列化漏洞超詳細(xì)講解9. Python中g(shù)lob庫實(shí)現(xiàn)文件名的匹配10. React基礎(chǔ)-JSX的本質(zhì)-虛擬DOM的創(chuàng)建過程實(shí)例分析
