IEEE 754 標準規定了計算機程序設計環境中的二進制和十進制的浮點數自述的交換、算術格式以及方法.javascript
現有存儲介質都是2進制。2進制的進制基數是2,那麼一個數字只要被因素包含大於2的質數的數除,都會產生無限循環小數。無限循環小數和無理數都沒法,和非無限循環的有理數一塊兒用同一種方式存儲到存儲介質上的同時還保持計算的兼容性。
對於無限循環小數,能夠設計一種格式存儲到介質上,可是同時又要和非無限循環的有理數可以計算,效率應該會變得很是低下。 對於無理數,小數位的數字沒有規律可循,因此根本沒法保存精確值,只能保存近似值。
高精度計算,通常能夠將數字轉發成string, 去掉小數點,按位計算再保存回string,再加回小數點。java
document.write (0.01 + 0.05); //輸出結果爲0.060000000000000005ide
document.write (0.09 + 0.01); //輸出結果爲0.09999999999999999函數
document.write(11*22.9); //輸出結果爲251.89999999999998工具
擴大倍數法:有多少位小數就擴大10的n次方this
document.write((0.01*100+0.09*100)/100); //輸出結果爲0.1spa
四捨五入法:prototype
document.write((0.01+0.09).toFixed(2)); //保留2位小數,輸出結果爲0.10設計
document.write(Math.round((0.01+0.09)*100)/100); //輸出結果爲0.1code
擴大倍數法:有多少位小數就擴大10的n次方
System.out.println((0.01*100+0.09*100)/100); //輸出結果爲0.1
四捨五入法:
System.out.println(Math.rint(0.01*100+0.09*100)/100); //輸出結果爲0.1
System.out.println(Math.round(0.01*100+0.09*100)/100); //輸出結果爲0.1
System.out.println(new BigDecimal(0.099).setScale(2, RoundingMode.HALF_UP).doubleValue()); //輸出結果爲0.10
備註: Java支持7中舍入法
一、 ROUND_UP:遠離零方向舍入。向絕對值最大的方向舍入,只要捨棄位非0即進位。
二、 ROUND_DOWN:趨向零方向舍入。向絕對值最小的方向輸入,全部的位都要捨棄,不存在進位狀況。
三、 ROUND_CEILING:向正無窮方向舍入。向正最大方向靠攏。如果正數,舍入行爲相似於ROUND_UP,若爲負數,舍入行爲相似於ROUND_DOWN。Math.round()方法就是使用的此模式。
四、 ROUND_FLOOR:向負無窮方向舍入。向負無窮方向靠攏。如果正數,舍入行爲相似於ROUND_DOWN;若爲負數,舍入行爲相似於ROUND_UP。
五、 HALF_UP:最近數字舍入(5進)。這是咱們最經典的四捨五入。
六、 HALF_DOWN:最近數字舍入(5舍)。在這裏5是要捨棄的。
七、 HALF_EVEN:銀行家舍入法。銀行家舍入法.
附錄一:js封裝四則運算
//除法函數,用來獲得精確的除法結果 //說明:javascript的除法結果會有偏差,在兩個浮點數相除的時候會比較明顯。這個函數返回較爲精確的除法結果。 //調用:accDiv(arg1,arg2) //返回值:arg1除以arg2的精確結果 function accDiv(arg1,arg2){ var t1=0,t2=0,r1,r2; try{t1=arg1.toString().split(".")[1].length}catch(e){} try{t2=arg2.toString().split(".")[1].length}catch(e){} with(Math){ r1=Number(arg1.toString().replace(".","")) r2=Number(arg2.toString().replace(".","")) return (r1/r2)*pow(10,t2-t1); } } //給Number類型增長一個div方法,調用起來更加方便。 Number.prototype.div = function (arg){ return accDiv(this, arg); } //乘法函數,用來獲得精確的乘法結果 //說明:javascript的乘法結果會有偏差,在兩個浮點數相乘的時候會比較明顯。這個函數返回較爲精確的乘法結果。 //調用:accMul(arg1,arg2) //返回值:arg1乘以arg2的精確結果 function accMul(arg1,arg2) { var m=0,s1=arg1.toString(),s2=arg2.toString(); try{m+=s1.split(".")[1].length}catch(e){} try{m+=s2.split(".")[1].length}catch(e){} return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m) } //給Number類型增長一個mul方法,調用起來更加方便。 Number.prototype.mul = function (arg){ return accMul(arg, this); } //加法函數,用來獲得精確的加法結果 //說明:javascript的加法結果會有偏差,在兩個浮點數相加的時候會比較明顯。這個函數返回較爲精確的加法結果。 //調用:accAdd(arg1,arg2) //返回值:arg1加上arg2的精確結果 function accAdd(arg1,arg2){ var r1,r2,m; try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0} m=Math.pow(10,Math.max(r1,r2)) return (arg1*m+arg2*m)/m } //給Number類型增長一個add方法,調用起來更加方便。 Number.prototype.add = function (arg){ return accAdd(arg,this); } //減法函數,用來獲得精確的減法結果 //說明:javascript的減法結果會有偏差,在兩個浮點數相加的時候會比較明顯。這個函數返回較爲精確的減法結果。 //調用:accSubtr(arg1,arg2) //返回值:arg1減去arg2的精確結果 function accSubtr(arg1,arg2){ var r1,r2,m,n; try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0} m=Math.pow(10,Math.max(r1,r2)); //動態控制精度長度 n=(r1>=r2)?r1:r2; return ((arg1*m-arg2*m)/m).toFixed(n); } //給Number類型增長一個subtr 方法,調用起來更加方便。 Number.prototype.subtr = function (arg){ return accSubtr(arg,this); }
附錄二:java工具類Arith
工具類Arith來簡化操做。它提供如下靜態方法,包括加減乘除和四捨五入: public static double add(double v1,double v2) public static double sub(double v1,double v2) public static double mul(double v1,double v2) public static double div(double v1,double v2) public static double div(double v1,double v2,int scale) public static double round(double v,int scale) 源文件Arith.java: import java.math.BigDecimal; /** * 因爲Java的簡單類型不可以精確的對浮點數進行運算,這個工具類提供精 * 確的浮點數運算,包括加減乘除和四捨五入。 */ public class Arith{ //默認除法運算精度 private static final int DEF_DIV_SCALE = 10; //這個類不能實例化 private Arith(){ } /** * 提供精確的加法運算。 * @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); } /** * 提供(相對)精確的除法運算。當發生除不盡的狀況時,由scale參數指 * 定精度,之後的數字四捨五入。 * @param v1 被除數 * @param v2 除數 * @param scale 表示表示須要精確到小數點之後幾位。 * @return 兩個參數的商 */ public static double div(double v1,double v2,int scale){ if(scale<0){ throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } /** * 提供精確的小數位四捨五入處理。 * @param v 須要四捨五入的數字 * @param scale 小數點後保留幾位 * @return 四捨五入後的結果 */ public static double round(double v,int scale){ if(scale<0){ throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(Double.toString(v)); BigDecimal one = new BigDecimal("1"); return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } };