首先看下下面的題目
public static void main(String[] args) {
float a = 1.0f;
float b = 0.9f;
float c = 0.8f;
System.out.println((a-b)==(b-c));
}
請(qǐng)問控制臺(tái)輸出的結(jié)果是:
A. true
B. false
不知道各位同學(xué)是怎么選的,換做之前的我肯定毫不猶豫的選擇A了空入。但是,在ide中運(yùn)行一下后控制臺(tái)給出的結(jié)果是false族檬。為啥呢歪赢?
浮點(diǎn)精度
浮點(diǎn)型數(shù)據(jù)類型,F(xiàn)LOAT 數(shù)據(jù)類型用于存儲(chǔ)單精度浮點(diǎn)數(shù)或雙精度浮點(diǎn)數(shù)单料。浮點(diǎn)數(shù)使用 IEEE(電氣和電子工程師協(xié)會(huì))格式埋凯。浮點(diǎn)類型的單精度值具有 4 個(gè)字節(jié),包括一個(gè)符號(hào)位扫尖、一個(gè) 8 位 excess-127 二進(jìn)制指數(shù)和一個(gè) 23 位尾數(shù)白对。尾數(shù)表示一個(gè)介于 1.0 和 2.0 之間的數(shù)。由于尾數(shù)的高順序位始終為 1换怖,因此它不是以數(shù)字形式存儲(chǔ)的甩恼。此表示形式為 float 類型提供了一個(gè)大約在 -3.4E+38 和 3.4E+38 之間的范圍。--引自百度
實(shí)際上我們的數(shù)字都是由2的冪數(shù)來湊成的沉颂。就如同上面的題目,兩個(gè)減法得出的結(jié)果的二進(jìn)制相似數(shù)是不同的所以控制臺(tái)答應(yīng)出來的結(jié)果是false钉蒲。
下面再舉個(gè)開發(fā)過程中遇到的一個(gè)坑
class Untitled {
public static void main(String[] args) {
float a = 3.01f;
float b = a % 1.0f;
System.out.println(b);
}
}
····
0.00999999
沒錯(cuò)它不是0.01,取模盡然是0.00999999接近1。所以float的運(yùn)算是不安全的仪搔。那我們?nèi)绾伪WC其計(jì)算結(jié)果不失真呢偏陪?
這個(gè)時(shí)候我們需要利用BigDecimal
class Untitled {
public static void main(String[] args) {
BigDecimal a =new BigDecimal("3.01");
BigDecimal b =new BigDecimal("1");
float c = a.remainder(b).floatValue();
System.out.println(c);
}
}
····
0.01
這里用字符串是因?yàn)樽址前次粊泶鎯?chǔ)的昌阿,自然數(shù)都是可以用2進(jìn)制精確表示的灶轰,所以這里使用字符串來實(shí)例化。詳細(xì)可以參考BigDecimal官方文檔