溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java中浮點數(shù)有哪些需要注意的問題

發(fā)布時間:2021-06-23 14:32:19 來源:億速云 閱讀:176 作者:chen 欄目:編程語言

這篇文章主要介紹“Java中浮點數(shù)有哪些需要注意的問題”,在日常操作中,相信很多人在Java中浮點數(shù)有哪些需要注意的問題問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java中浮點數(shù)有哪些需要注意的問題”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

基本數(shù)據(jù)類型

Java中浮點數(shù)有哪些需要注意的問題


Java中浮點數(shù)有哪些需要注意的問題

Java中浮點數(shù)有哪些需要注意的問題

Java中浮點數(shù)有哪些需要注意的問題

Java中浮點數(shù)有哪些需要注意的問題


浮點數(shù)存在誤差

浮點數(shù)有一個需要特別注意的點就是浮點數(shù)是有誤差的,比如以下這段代碼你覺得輸出的什么結(jié)果:

public class Demo {
	public static void main(String[] args) {
		System.out.println(0.1+0.2 == 0.3);//輸出false
	}
}

這段代碼輸出值是false,之所以是這個結(jié)果那是因為浮點數(shù)是存在誤差的,也就yi是說0.1在計算機(jī)中存儲時不是精確的0.1,而有可能是0.1000000001,或者其他數(shù),而0.2或0.3也是如此,所以0.1+0.2和0.3在計算機(jī)中是不相等的。

因為浮點數(shù)存在這個特性,所以我們在編程中間要盡量避免用浮點數(shù)進(jìn)行比較。

如果非要用浮點數(shù)進(jìn)行比較的話,那可以使用下面這個方法:

public class Demo {
	public static void main(String[] args) {
		float n = (float)1e-6;//表示10的-6次方
		System.out.println(0.1+0.2 - 0.3 < n);//輸出true
	}
}

以上代碼的輸出值是true,該方法的原理是如果兩個數(shù)相差足夠小,小到可以忽略不記的話,這里的界限設(shè)置是10的-6次方,那證明比較的這兩個數(shù)可以認(rèn)為是相等的,此方法只能在所表示的浮點數(shù)的小數(shù)點后的位數(shù)不是很多的時候使用。

接下來我們再來看一種極端的情況,代碼如下:

public class Demo {
	public static void main(String[] args) {
		System.out.println(0.30000000000000001 == 0.3);//輸出true
	}
}

以上的代碼輸出true,但其實我們?nèi)庋劭梢院苤庇^的看出,這兩個數(shù)雖然很接近,但他們絕對不相等,像這種極端的數(shù)我們是無法用上面的方法進(jìn)行比較的,所以還是記住這句話:盡量避免對浮點數(shù)進(jìn)行比較。

Java中浮點數(shù)有哪些需要注意的問題

Java中浮點數(shù)有哪些需要注意的問題


BigDecimal類

我們既然知道了浮點數(shù)是存在誤差的,所以在數(shù)據(jù)本身需要準(zhǔn)確精度存儲時,我們是一定不會使用float和double的,比如金錢數(shù)額的存儲。這時我們通常使用BigDecimal類進(jìn)行存儲,它是一個可以存儲準(zhǔn)確浮點數(shù)的類。

Java中浮點數(shù)有哪些需要注意的問題


  1. BigDecimal類的定義:

   BigDecimal bd = new BigDecimal("123.456");
  1. BigDecimal使用scale()表示小數(shù)位數(shù),例如:

   BigDecimal d1 = new BigDecimal("987.65");
   BigDecimal d2 = new BigDecimal("987.6500");
   BigDecimal d3 = new BigDecimal("98765400");
   System.out.println(d1.scale()); // 2,表示兩位小數(shù)
   System.out.println(d2.scale()); // 4
   System.out.println(d3.scale()); // 0
  1. BigDecimal中的stripTrailingZeros()方法,可以將BigDecimal格式化為去掉數(shù)值末尾0的相等的數(shù):

   BigDecimal d1 = new BigDecimal("123.4500");
   BigDecimal d2 = d1.stripTrailingZeros();
   System.out.println(d1+" "+d1.scale()); // 123.4500  4
   System.out.println(d2+" "+d2.scale()); // 123.45  2,因為去掉了00
   
   BigDecimal d3 = new BigDecimal("1234500");
   BigDecimal d4 = d3.stripTrailingZeros();
   System.out.println(d3+" "+d3.scale()); // 1234500  0
   System.out.println(d4+" "+d4.scale()); // 1.2345E+6  -2

BigDecimalscale()返回負(fù)數(shù),例如,-2,表示這個數(shù)是個整數(shù),并且末尾有2個0。以上的d4就是如此,去掉0后數(shù)值沒變,只是換了一種表示方法。

  1. BigDecimal可以設(shè)置它的scale,如果精度比原始值低,那么按照指定的方法進(jìn)行四舍五入或者直接截斷:

   import java.math.BigDecimal;
   import java.math.RoundingMode;
   
   public class Demo {
   	public static void main(String[] args) {
   		BigDecimal d1 = new BigDecimal("123.456789");
           BigDecimal d2 = d1.setScale(4, RoundingMode.HALF_UP); // 四舍五入,123.4568
           BigDecimal d3 = d1.setScale(4, RoundingMode.DOWN); // 直接截斷,123.4567
           System.out.println(d2);//123.4568
           System.out.println(d3);//123.4567
   	}
   }
  1. BigDecimal的加、減、乘、除:

   import java.math.BigDecimal;
   
   public class Demo {
   	public static void main(String[] args) {
   		BigDecimal d1 = new BigDecimal("124.44");
           BigDecimal d2 = new BigDecimal("12.2");
           System.out.println(d1.add(d2));//d1+d2   136.64
           System.out.println(d1.subtract(d2));//d1-d2  112.24
           System.out.println(d1.multiply(d2));//d1*d2  1518.168
           System.out.println(d1.divide(d2));//d1/d2   10.2
   	}
   }
  1. BigDecimal在做加、減、乘時,精度不會丟失,但是做除法時,存在無法除盡的情況,這時就必須指定精度以及如何進(jìn)行截斷:

   import java.math.BigDecimal;
   import java.math.RoundingMode;
   
   public class Demo {
   	public static void main(String[] args) {
   		BigDecimal d1 = new BigDecimal("123.456");
   		BigDecimal d2 = new BigDecimal("23.456789");
   		BigDecimal d3 = d1.divide(d2, 10, RoundingMode.HALF_UP); // 保留10位小數(shù)并四舍五入
   		BigDecimal d4 = d1.divide(d2); // 報錯:ArithmeticException,因為除不盡
   	}
   }
  1. 可以對BigDecimal做除法的同時求其余數(shù):

   import java.math.BigDecimal;
   public class Demo {
   	public static void main(String[] args) {
   		BigDecimal n = new BigDecimal("22.444");
           BigDecimal m = new BigDecimal("0.23");
           BigDecimal[] dr = n.divideAndRemainder(m);
           System.out.println(dr[0]); // 97.0
           System.out.println(dr[1]); // 0.134
   	}
   }
  1. 調(diào)用divideAndRemainder()方法時,返回的數(shù)組包含兩個BigDecimal,第一個是商,第二個是余數(shù),商總是整數(shù),余數(shù)不會大于余數(shù),我們可以利用該方法判斷兩個BigDecimal是否是整數(shù)倍數(shù):

   BigDecimal n = new BigDecimal("12.34");
   BigDecimal m = new BigDecimal("0.12");
   BigDecimal[] dr = n.divideAndRemainder(m);
   if (dr[1].signum() == 0) {//signum()會基于此BigDecimal返回三個值-1、1、0,分別對應(yīng)為該數(shù)小于0,大于0和等于0
       // n是m的整數(shù)倍
   }
  1. 比較兩個BigDecimal的值是否相等時,要注意的是,使用equals()方法不但要求兩個BigDecimal的值相等,還要求它們的scale()相等:

   BigDecimal d1 = new BigDecimal("123.45");
   BigDecimal d2 = new BigDecimal("123.45000");
   System.out.println(d1.equals(d2)); // false,因為scale不同
   System.out.println(d1.equals(d2.stripTrailingZeros())); // true,因為d2去除尾部0后scale變?yōu)?,與d1相同

注意:使用compareTo()來比較兩個BigDecimal的值,不要用equals()

  1. 使用compareTo()方法來比較兩數(shù)大小,它根據(jù)兩個值的大小分別返回-1、1和0,分別表示小于、大于和等于。

    import java.math.BigDecimal;
    public class Demo {
    	public static void main(String[] args) {
    		BigDecimal d1 = new BigDecimal("123.45");
    		BigDecimal d2 = new BigDecimal("123.45000");
    		BigDecimal d3 = new BigDecimal("123.40");
    		System.out.println(d1.compareTo(d2)); // 0
    		System.out.println(d1.compareTo(d3));//  1
    		System.out.println(d3.compareTo(d2));// -1
    	}
    }
  1. 查看BigDecimal的源碼,可以發(fā)現(xiàn)一個BigDecimal是通過一個BigInteger和一個scale來表示的,即BigInteger表示一個完整的整數(shù),而scale表示小數(shù)位數(shù):

    public class BigDecimal extends Number implements Comparable<BigDecimal> {
        private final BigInteger intVal;
        private final int scale;
    }

Java中浮點數(shù)有哪些需要注意的問題

Java中浮點數(shù)有哪些需要注意的問題

Java中浮點數(shù)有哪些需要注意的問題

Java中浮點數(shù)有哪些需要注意的問題

Java中浮點數(shù)有哪些需要注意的問題

到此,關(guān)于“Java中浮點數(shù)有哪些需要注意的問題”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI