争怎路由网/网站教程/内容

javascript对于计算精度的一些小知识(总结)

网站教程2024-06-03 阅读
网页的本质就是超级文本标记语言,通过结合使用其他的Web技术(如:脚本语言、公共网关接口、组件等),可以创造出功能强大的网页。因而,超级文本标记语言是万维网(Web)编程的基础,也就是说万维网是建立在超文本基础之上的。超级文本标记语言之所以称为超文本标记语言,是因为文本中包含了所谓“超级链接”点。
本章给大家介绍关于javascript中计算精度的一些小知识(总结),让大家了解十进制之间二进制是如何转换的、javascript是如何保存数字的、 javascript是如何读取数字的,最后实例讲解 javascript如何解决精度问题出现的计算错误问题。有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

一. 前置知识点

1. 十进制如何转为二进制?

整数部分除二取余数, 直到商为0,逆序排列,小数部分乘2取整,顺序排列,直到积中小数部分为0或者到达要求精度。

8转为二进制是多少?

8 / 2 = 4...0  取0
4 / 2 = 2...0  取0
2 / 2 = 1...0  取0
1 / 2 = 0...1  取1

二进制结果为:1000

0.25转为二进制是多少?

0.25 * 2 = 0.50  取0
0.50 * 2 = 1.00  取1

二进制结果为:01

于是可得出8.25的二进制表示:1000.01

2. 二进制如何转为十进制?

注意:二进制转为十进制不分整数部分与小数部分。

二进制1000.01转为十进制

1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 0 * 2^0 + 0 * 2^-1 + 0 * 2^-2 = 8.25

二. javascript是如何保存数字的

JavaScript 里的数字是采用 IEEE 754 标准的 64 位 double 双精度浮点数

1.jpg

对于没有接触的人来说,以上可能理解起来很模糊,没关系,接下来我们用案例具体说明其流程,先看一下上述的十进制数8.25在JS中是如何保存的。

注意:

三. javascript是如何读取数字的

我们还是以8.25的二进制0-10000000011-0000100000000000000000000000000000000000000000000000来讲述

  1. 首先我们获取指数部分的二进制1000000001,转化为十进制为1027,1027减去1023就是我们实际的指数4了;

  2. 获取尾数部分0000100000000000000000000000000000000000000000000000实际是0.00001(后面的0就不写了),然后加上我们忽略的1,得出1.00001;

  3. 因为首位为0,所以我们的数为正数,得出二进制的科学计数为1.00001 * 2^4,接着再转为十进制数,就得到了我们的8.25;

四. 从0.1+0.2来看javascript精度问题

这里就要进入我们的正题了,看懂了前面的原理说明,这部分将会变得很好理解了。

要计算0.1+0.2,首先计算要先读取到这两个浮点数

0.1存储为64位二进制浮点数

没有忘记以上步骤吧

  1. 先将0.1转化为二进制的整数部分为0,小数部分为:0001100110011001100110011001100110011...咦,这里居然进入了无限循环,那怎么办呢?暂时先不管;

  2. 我们得到的无限循环的二进制数用科学计数表示为1.100110011001100110011001100110011... * 2^-4;

  3. 指数位即是-4 + 1023 = 1019,转化位11位二进制数01111111011;

  4. 尾数位是无限循环的,但是双精度浮点数规定尾数位52位,于是超出52位的将被略去,保留1001100110011001100110011001100110011001100110011010

  5. 最后得出0.1的64位二进制浮点数:0-01111111011-1001100110011001100110011001100110011001100110011010

同上,0.2存储为64位二进制浮点数:0-01111111100-1001100110011001100110011001100110011001100110011010

读取到两个浮点数的64为二进制后,再将其转化为可计算的二进制数

  1. 0.1转化为1.1001100110011001100110011001100110011001100110011010 * 2^(1019 - 1023)——0.00011001100110011001100110011001100110011001100110011010;

  2. 0.2转化为1.1001100110011001100110011001100110011001100110011010 * 2^(1020 - 1023)——0.0011001100110011001100110011001100110011001100110011010;

接着将两个浮点数的二进制数进行加法运算,得出0.0100110011001100110011001100110011001100110011001100111转化为十进制数即为0.30000000000000004

不难看出,精度缺失是在存储这一步就丢失了,后面的计算只是在不精准的值上进行的运算。

五. javascript如何解决精度问题出现的计算错误问题

对于小数或者整数的简单运算可如下解决:

function numAdd(num1, num2) { 
  let baseNum, baseNum1, baseNum2; 
  try { 
    baseNum1 = String(num1).split(".")[1].length; 
  } catch (e) { 
    baseNum1 = 0; 
  } 
  try { 
    baseNum2 = String(num2).split(".")[1].length; 
  } catch (e) { 
    baseNum2 = 0;
  } 
  baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
  return (num1 * baseNum + num2 * baseNum) / baseNum;
};

如:0.1 + 0.2 通过函数处理后,相当于 (0.1 * 10 + 0.2 * 10) / 10

但是如同我们前面所了解的,浮点数在存储的时候就已经丢失精度了,所以浮点数乘以一个基数仍然会存在精度缺失问题,比如2500.01 * 100 = 250001.00000000003, 所以我们可以在以上函数的结果之上使用toFixed(),保留需要的小数位数。

一些复杂的计算,可以引入一些库进行解决

以上就是javascript关于计算精度的一些小知识(总结)的详细内容,更多请关注php中文网其它相关文章!

  • 微信

  • 网站建设是一个广义的术语,涵盖了许多不同的技能和学科中所使用的生产和维护的网站。



    ……

    标签:javascript对于计算精度的一些小知识(总结)
    相关阅读