tags: ‘js’

categories: ‘js’

js计算丢失精度问题(加法、减法、乘法、除法)

方法一: 原型

  1. // 加法
  2. Number.prototype.add = function(arg){
  3. var r1,r2,m;
  4. try{
  5. r1=this.toString().split(".")[1].length
  6. }catch(e){
  7. r1=0
  8. }
  9. try{
  10. r2=arg.toString().split(".")[1].length
  11. }catch(e){
  12. r2=0
  13. }
  14. m = Math.pow(10,Math.max(r1,r2));
  15. return Math.round(this*m+arg*m)/m
  16. }
  17. 0.1+0.2 // 0.30000000000000004
  18. 0.1.add(0.2) // 0.3
  19. // 减法
  20. Number.prototype.sub = function (arg){
  21. return this.add(-arg);
  22. }
  23. 0.3-0.1 // 0.19999999999999998
  24. 0.3.sub(0.1) // 0.2
  25. 5000.02.sub(905.8) // 4094.22
  26. // 乘法
  27. Number.prototype.mul = function (arg){
  28. var m=0,s1=this.toString(),s2=arg.toString();
  29. try{
  30. m+=s1.split(".")[1].length
  31. }catch(e){}
  32. try{
  33. m+=s2.split(".")[1].length
  34. }catch(e){}
  35. return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m)
  36. }
  37. 0.00035.mul(100) // 0.035
  38. // 除法
  39. Number.prototype.div = function (arg){
  40. var t1=0,t2=0,r1,r2;
  41. try{
  42. t1=this.toString().split(".")[1].length
  43. }catch(e){}
  44. try{
  45. t2=arg.toString().split(".")[1].length
  46. }catch(e){}
  47. with(Math){
  48. r1=Number(this.toString().replace(".",""))
  49. r2=Number(arg.toString().replace(".",""))
  50. return (r1/r2)*pow(10,t2-t1);
  51. }
  52. }

方法二: 将小数化成整数后再作运算

  1. /**
  2. * 加法运算,避免数据相加小数点后产生多位数和计算精度损失。
  3. *
  4. * @param num1加数1 | num2加数2
  5. */
  6. function numAdd(num1, num2) {
  7. var baseNum, baseNum1, baseNum2;
  8. try {
  9. baseNum1 = num1.toString().split(".")[1].length;
  10. } catch (e) {
  11. baseNum1 = 0;
  12. }
  13. try {
  14. baseNum2 = num2.toString().split(".")[1].length;
  15. } catch (e) {
  16. baseNum2 = 0;
  17. }
  18. baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
  19. return (num1 * baseNum + num2 * baseNum) / baseNum;
  20. };
  21. /**
  22. * 加法运算,避免数据相减小数点后产生多位数和计算精度损失。
  23. *
  24. * @param num1被减数 | num2减数
  25. */
  26. function numSub(num1, num2) {
  27. var baseNum, baseNum1, baseNum2;
  28. var precision;// 精度
  29. try {
  30. baseNum1 = num1.toString().split(".")[1].length;
  31. } catch (e) {
  32. baseNum1 = 0;
  33. }
  34. try {
  35. baseNum2 = num2.toString().split(".")[1].length;
  36. } catch (e) {
  37. baseNum2 = 0;
  38. }
  39. baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
  40. precision = (baseNum1 >= baseNum2) ? baseNum1 : baseNum2;
  41. return ((num1 * baseNum - num2 * baseNum) / baseNum).toFixed(precision);
  42. };
  43. /**
  44. * 乘法运算,避免数据相乘小数点后产生多位数和计算精度损失。
  45. *
  46. * @param num1被乘数 | num2乘数
  47. */
  48. function numMulti(num1, num2) {
  49. var baseNum = 0;
  50. try {
  51. baseNum += num1.toString().split(".")[1].length;
  52. } catch (e) {
  53. }
  54. try {
  55. baseNum += num2.toString().split(".")[1].length;
  56. } catch (e) {
  57. }
  58. return Number(num1.toString().replace(".", "")) * Number(num2.toString().replace(".", "")) / Math.pow(10, baseNum);
  59. };
  60. /**
  61. * 除法运算,避免数据相除小数点后产生多位数和计算精度损失。
  62. *
  63. * @param num1被除数 | num2除数
  64. */
  65. function numDiv(num1, num2) {
  66. var baseNum1 = 0, baseNum2 = 0;
  67. var baseNum3, baseNum4;
  68. try {
  69. baseNum1 = num1.toString().split(".")[1].length;
  70. } catch (e) {
  71. baseNum1 = 0;
  72. }
  73. try {
  74. baseNum2 = num2.toString().split(".")[1].length;
  75. } catch (e) {
  76. baseNum2 = 0;
  77. }
  78. with (Math) {
  79. baseNum3 = Number(num1.toString().replace(".", ""));
  80. baseNum4 = Number(num2.toString().replace(".", ""));
  81. return (baseNum3 / baseNum4) * pow(10, baseNum2 - baseNum1);
  82. }
  83. };

参考文献

js 计算精度问题,及解决办法
JS 四则运算(加减乘除小数运算)避免损失精度