js 小數點計算精度問題
阿新 • • 發佈:2022-12-05
/* 由於很多時候都會設計到浮點小數的演算法,
* 在JS 中只用普通的parseFlost之類的進信封資料型別轉換會使資料失去精度 * 因此採用先轉整數再計算的方式 * */ //浮點數相加function dcmAdd(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 (accMul(arg1,m)+accMul(arg2,m))/m; }
//浮點數相減
/* * 說明同上面的加法 * */function dcmSub(arg1,arg2){ return dcmAdd(arg1,-arg2); }//浮點數取餘數 /* * 跟據實際中的案例很容易喪失精度,通常做法是同時擴大10000倍,但考慮 * 跟前有關因此還是採用先轉整數再計算 * */
function dcmYu(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 (accMul(arg1,m)%accMul(arg2,m))/m; }
/* 除法函式,用來得到精確的除法結果
說明:javascript的除法結果會有誤差,在兩個浮點數相除的時候會比較明顯。這個函式返回 較為精確的除法結果。 呼叫:accDiv(arg1,arg2) 返回值:arg1除以arg2的精確結果 */function accDiv(arg1,arg2){/* 乘法函式,用來得到精確的乘法結果 說明:javascript的乘法結果會有誤差,在兩個浮點數相乘的時候會比較明顯。這個函式返回較為精確的乘法結果。 呼叫:accMul(arg1,arg2) 返回值: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); } }
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) }// 轉化成小數, 原函式toDecimal(datavalue)存在的精度問題,因涉及過多遮蔽。
function toDecimal(datevalue){ if(datevalue.indexOf('%') != -1){ datevalue = datevalue.replace(/%/g,''); if(datevalue.indexOf(',') != -1) { datevalue = datevalue.replace(/,/g,''); } // 除100精度在原有基礎上增加2位。 var decimal = (datevalue.indexOf('.') == -1) ? 0 : (datevalue.length - datevalue.indexOf('.') - 1); datevalue = accDiv(datevalue, 100).toFixed(decimal + 2); // alert("toDecimal: " + datevalue); } else { if(datevalue.indexOf(',') != -1){ datevalue = datevalue.replace(/,/g,''); } } return datevalue; }
// 將小數轉換為百分數。 function toPercentFormat(datevalue) { var aa = accMul(datevalue, 100); return "" + aa + "%"; }* 在JS 中只用普通的parseFlost之類的進信封資料型別轉換會使資料失去精度 * 因此採用先轉整數再計算的方式 * */ //浮點數相加
function dcmAdd(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 (accMul(arg1,m)+accMul(arg2,m))/m; }
//浮點數相減
/* * 說明同上面的加法 * */function dcmSub(arg1,arg2){ return dcmAdd(arg1,-arg2); }//浮點數取餘數 /* * 跟據實際中的案例很容易喪失精度,通常做法是同時擴大10000倍,但考慮 * 跟前有關因此還是採用先轉整數再計算 * */
function dcmYu(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 (accMul(arg1,m)%accMul(arg2,m))/m; }
/* 除法函式,用來得到精確的除法結果
說明: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); } }/* 乘法函式,用來得到精確的乘法結果 說明: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) }// 轉化成小數, 原函式toDecimal(datavalue)存在的精度問題,因涉及過多遮蔽。
function toDecimal(datevalue){ if(datevalue.indexOf('%') != -1){ datevalue = datevalue.replace(/%/g,''); if(datevalue.indexOf(',') != -1) { datevalue = datevalue.replace(/,/g,''); } // 除100精度在原有基礎上增加2位。 var decimal = (datevalue.indexOf('.') == -1) ? 0 : (datevalue.length - datevalue.indexOf('.') - 1); datevalue = accDiv(datevalue, 100).toFixed(decimal + 2); // alert("toDecimal: " + datevalue); } else { if(datevalue.indexOf(',') != -1){ datevalue = datevalue.replace(/,/g,''); } } return datevalue; }
// 將小數轉換為百分數。 function toPercentFormat(datevalue) { var aa = accMul(datevalue, 100); return "" + aa + "%"; }