【 Android 】float / double 計算失去精度
今天在數值運算的時候,發現一個問題:
您可以使用Binary Coded Decimal (BCD)来保持精度。BCD數字編碼方法會把每一个十進制數字單獨編碼;BCD碼的主要優點是在機器格式與人可讀的格式之間轉換容易,以及十進制數值的高精度表示。BCD碼的主要缺點是增加了實現算術運算的電路的複雜度,以及儲存效率低。
而在android裡有以下方法可以運算浮點數:
1. Math.round(value*100)/100.0;
2. Math.floor(seekbarInvalue*100)/100.0;
//Math.floor()方法會傳回小於或等於給定數值(輸入參數)的最大整數。
3. DecimalFormat df = new DecimalFormat("#0.00");
double Value = new Double(df.format(value));
//DecimalFormat用法
4. 使用math.BigDecimal 的運算是精度較高的方式,並且一定要轉作string
/**
* 提供精确的加法运算。
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1,double v2){
return div(v1,v2,DEF_DIV_SCALE);
}
getValue = 1619;
seekbarInvalue = getValue * 0.01;
seekbarInvalue += 0.1;
運算出來的結果是:
為什麼浮點數會失去精度?
A: 二進制表示可能不夠精確,浮點數值沒辦法用十進制來精確表示的原因可能是cpu表示的浮點數的方法,若是這樣就需要在運算的時候犧牲一些精度; 例如2.4的二進制表示並非是2.4,而是最接近的表示是2.3999999999999999。
而在android裡有以下方法可以運算浮點數:
1. Math.round(value*100)/100.0;
//返回x最接近的整数,如果x的小数部分大于等于0.5,返回值是大于x的最小整数,否则round函数返回小于等于x的最大整数
2. Math.floor(seekbarInvalue*100)/100.0;
//Math.floor()方法會傳回小於或等於給定數值(輸入參數)的最大整數。
3. DecimalFormat df = new DecimalFormat("#0.00");
double Value = new Double(df.format(value));
//DecimalFormat用法
4. 使用math.BigDecimal 的運算是精度較高的方式,並且一定要轉作string
/**
* 提供精确的加法运算。
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1,double v2){
return div(v1,v2,DEF_DIV_SCALE);
}
留言
張貼留言