計(jì)算機(jī)的數(shù)值采用的是二進(jìn)制形式存儲(chǔ)飘弧。
根據(jù)IEEE754標(biāo)準(zhǔn)拓萌,
單精度浮點(diǎn)數(shù)為32位:
- | sign | exponent | fraction |
---|---|---|---|
位數(shù) | 1 bit | 8 bit | 23 bit |
編號(hào)(右起) | 31 | 30 ~ 23 | 22 ~ 0 |
雙精度浮點(diǎn)數(shù)為64位:
- | sign | exponent | fraction |
---|---|---|---|
位數(shù) | 1 bit | 11 bit | 52 bit |
編號(hào) | 63 | 62 ~ 52 | 51 ~ 0 |
0.99用的有效數(shù)字部分(fraction):
0.99 * 2 = 1+0.98 --> 1
0.98 * 2 = 1+ 0.96 --> 1
0.96 * 2 = 1+0.92 -- >1
0.92 * 2 = 1+0.84 -- >1...............
所以計(jì)算機(jī)二進(jìn)制無(wú)法精確表示浮點(diǎn)數(shù)滔岳,精度有損失搓谆。示例代碼如下:
public class FloatTrap {
public static void main(String[] args) {
double a = 1;
double b = 0.99;
System.out.println(a - b);
}
}//:output
//0.010000000000000009
java的浮點(diǎn)類(lèi)型有double(雙精度)和float(單精度)连锯。對(duì)于精確的浮點(diǎn)數(shù)運(yùn)算可以使用java.math.BigDecimal類(lèi),但是這樣依然會(huì)有精度損失渤刃。最佳的方法是使用string轉(zhuǎn)double或者float起愈,這樣是沒(méi)有精度損失的只恨。
使用BigDecimal類(lèi)示例
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
double a = 2.0;
double b = 1.9;
System.out.println(2.0 - 1.9);
System.out.println(Main.round(Main.subtract(a,b)));
}
/*精確的浮點(diǎn)數(shù)計(jì)算*/
private static double subtract(double m, double n){
BigDecimal tm = new BigDecimal(Double.toString(m));
BigDecimal tn = new BigDecimal(Double.toString(n));
return tm.subtract(tn).doubleValue();
}
/*四舍五入保留*/
private static double round(double target){
BigDecimal tmp = new BigDecimal(Double.toString(target));
BigDecimal one = new BigDecimal(Double.toString(1.0));
return tmp.divide(one,BigDecimal.ROUND_HALF_UP).doubleValue();
}
private static double div(double tm,double tn){
BigDecimal tempM = new BigDecimal(Double.toString(tm));
BigDecimal tempN = new BigDecimal(Double.toString(tn));
return tempM.divide(tempN,10, BigDecimal.ROUND_HALF_UP).doubleValue();
}
private static double add(double tm, double tn){
BigDecimal tempM = new BigDecimal(Double.toString(tm));
BigDecimal tempN = new BigDecimal(Double.toString(tn));
return tempM.add(tempN).doubleValue();
}
}