Javascript浮点数运算

╰半夏微凉° 2021-07-04 22:42 647阅读 0赞

浮点数

JavaScript中的小数采用的是双精度(64位)表示的,由三部分组成:

符 + 阶码 + 尾数

在二进制中,0.1 == 0.0001100110011001100110011001100110011001100110011001…(1001 循环)。因为浮点数只有52位有效数字,从第53位开始,就舍入了。这样就造成了“浮点数精度损失”问题。

浮点数问题

举证:
在这里插入图片描述在这里插入图片描述

第一阶段

收集的方法,仅可供参考思路,慎用

  1. /** * 除法函数 * @param {number} arg1 * @param {number} arg2 * @return {number} */
  2. function accDiv(arg1,arg2){
  3. var t1=0,t2=0,r1,r2;
  4. try{ t1=arg1.toString().split(".")[1].length}catch(e){ }
  5. try{ t2=arg2.toString().split(".")[1].length}catch(e){ }
  6. with(Math){
  7. r1=Number(arg1.toString().replace(".",""))
  8. r2=Number(arg2.toString().replace(".",""))
  9. return (r1/r2)*pow(10,t2-t1);
  10. }
  11. }
  12. function accDiv(arg1,arg2){
  13. var r1=0,r2=0,m,s1=arg1.toString(),s2=arg2.toString();
  14. try{
  15. if(s1.split(".")[1] != undefined )
  16. r1=s1.split(".")[1].length;
  17. }catch(e){ }
  18. try{
  19. if(s2.split(".")[1] != undefined )
  20. r2=s2.split(".")[1].length;
  21. }catch(e){ }
  22. m=Math.pow(10,Math.max(r1,r2));
  23. return (accMul(arg1,m))/(accMul(arg2,m));
  24. }
  25. /** * 乘法函数 * @param {number} arg1 * @param {number} arg2 * @return {number} */
  26. function accMul(arg1,arg2) {
  27. var m=0,s1=arg1.toString(),s2=arg2.toString();
  28. try{ m+=s1.split(".")[1].length}catch(e){ }
  29. try{ m+=s2.split(".")[1].length}catch(e){ }
  30. return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m)
  31. }
  32. function accMul(arg1,arg2){
  33. var m=0,s1=arg1.toString(),s2=arg2.toString();
  34. try{
  35. if(s1.split(".")[1] != undefined )
  36. m+=s1.split(".")[1].length
  37. }catch(e){ }
  38. try{
  39. if(s2.split(".")[1] != undefined )
  40. m+=s2.split(".")[1].length
  41. }catch(e){ }
  42. return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m)
  43. }
  44. /** * 加法函数 * @param {number} arg1 * @param {number} arg2 * @return {number} */
  45. function accAdd(arg1,arg2){
  46. var r1,r2,m;
  47. try{ r1=arg1.toString().split(".")[1].length}catch(e){ r1=0}
  48. try{ r2=arg2.toString().split(".")[1].length}catch(e){ r2=0}
  49. m=Math.pow(10,Math.max(r1,r2))
  50. return (arg1*m+arg2*m)/m
  51. }
  52. function accAdd(arg1,arg2){
  53. var r1=0,r2=0,m,s1=arg1.toString(),s2=arg2.toString();
  54. try{
  55. if(s1.split(".")[1] != undefined )
  56. r1=s1.split(".")[1].length;
  57. }catch(e){ }
  58. try{
  59. if(s2.split(".")[1] != undefined )
  60. r2=s2.split(".")[1].length;
  61. }catch(e){ }
  62. m=Math.pow(10,Math.max(r1,r2));
  63. return (accMul(arg1,m)+accMul(arg2,m))/m;
  64. }
  65. /** * 减法函数 * @param {number} arg1 * @param {number} arg2 * @return {number} */
  66. function Subtr(arg1,arg2){
  67. var r1,r2,m,n;
  68. try{ r1=arg1.toString().split(".")[1].length}catch(e){ r1=0}
  69. try{ r2=arg2.toString().split(".")[1].length}catch(e){ r2=0}
  70. m=Math.pow(10,Math.max(r1,r2));
  71. //last modify by deeka
  72. //动态控制精度长度
  73. n=(r1>=r2)?r1:r2;
  74. return ((arg1*m-arg2*m)/m).toFixed(n);
  75. }
  76. function Subtr(arg1,arg2){
  77. var r1=0,r2=0,m,n,s1=arg1.toString(),s2=arg2.toString();
  78. try{
  79. if(s1.split(".")[1] != undefined )
  80. r1=s1.split(".")[1].length;
  81. }catch(e){ }
  82. try{
  83. if(s2.split(".")[1] != undefined )
  84. r2=s2.split(".")[1].length;
  85. }catch(e){ }
  86. m=Math.pow(10,Math.max(r1,r2));
  87. //last modify by deeka
  88. //动态控制精度长度
  89. n=(r1>=r2)?r1:r2;
  90. return (accMul(arg1,m)-accMul(arg2,m))/m;
  91. }

第二阶段

取float型小数点后两位,例22.127456取成22.13

  1. function get(num){
  2. var str = s.toString();
  3. return s.substring(0,s.indexOf(".")+3);
  4. }
  5. function get(num){
  6. return s.toString().replace(/([0-9]\.[0-9]{2})[0-9]*/,"$1");
  7. }
  8. // 好风凭借力,送我上青云
  9. function get(num){
  10. return Math.round(num*100)/100;
  11. }
  12. function get(num){
  13. return num.toFixed(2);
  14. }

这里还是不可取的,仍需要具体

toFixed

  • numObj.toFixed([fractionDigits])

toFixed 方法返回一个以定点表示法表示的数字的字符串形式。该字符串中小数点之前有一位有效数字,而且其后必须包含 fractionDigits 数字。如果没有 fractionDigits 参数,或者该参数为 undefined,toFixed 方法假定该值为 0。

弊端:

  1. 0.009.toFixed(2)

在ie7下四舍五入是不稳定的,有些参数运算会显示0.00,而ff会是0.01。

替代方案:

  1. Number.prototype.toFixed = function(num){
  2. return (parseInt(this*Math.pow(10,num)+0.5)/Math.pow(10,num)).toString();
  3. }

with

  1. with (object)
  2. statements

with 语句通常用来缩短特定情形下必须写的代码量。

  1. with (Math){
  2. x = cos(3 * PI) + sin (LN10)
  3. y = tan(14 * E)
  4. }

第三阶段

精确范围判定

  1. var x = 0.2;
  2. var y = 0.3;
  3. var equal = (Math.abs(x - y) < 0.000001)

保留精度

函数toPrecisiontoFixed来保留一定的精度

  1. (0.1 + 0.2).toPrecision(10) == 0.3
  2. // or
  3. (0.1 + 0.2).toFixed(10) == 0.3

浮点数!=小数

整数和小数是数学里面的概念,在计算机中,只有定点数和浮点数,没有整数和小数。

计算机可精确的数字:

  • 一个奇数 0.5
  • 一个偶数 0.0。

人为的在数据最后一位补 5, 也就是 0.15,这样牺牲一位,但是可以保证数据精度,还原再把那个尾巴 5 去掉。

  1. JSON.parse('{"status":1,"id":9986705337161735,"name":"test"}').id;
  2. ==> 9986705337161736

发表评论

表情:
评论列表 (有 0 条评论,647人围观)

还没有评论,来说两句吧...

相关阅读

    相关 点数运算

    今天学习了浮点数运算(加减乘除)。浮点数运算主要包括两部分:指数运算和尾数运算。在IEEE754标准下,指数运算就是阶码的运算,类似于无符号数运算。尾数运算是原码运算。之前一直