复现与概述

当JS在进行浮点数运算时可能产生丢失精度的情况:

从肉眼可见的程度上观察,发生精度丢失的浮点数是没有规律的,但该浮点数丢失精度的问题会100%复现。经查阅,这个问题要追溯至浮点数的二进制存储方式,然而就高数而言,无限接近1的0.999999…和1是等价的,1 / ∞ ≈ 0 同理,在二进制中也同样存在这一情况。

找到原因

现在寻找浮点数的精度丢失问题跟二进制存储到底存在什么联系。

JavaScript引擎 - v8核心代码中,对于小数存储位双精度浮点,即64位保存的,但是这64位又分为三部分:

由于52位尾数用于记录数值,所以前端的精准位数应该是2^53-1即15位。当超过15位的时候就会出现精度损失。

例如小数2.55的储存方式:

最后的52位是一个1000110011001100的有限循环,但对于计算机来说,可以微妙的察觉到上文提到的两对参数失精问题大概就是由此而来:

再谈谈toFixed(n),它的处理方式就是在尾数位上减去第n位以外的小数,然后判断剩下的尾数是否大于2^-(n+1),大于等于就进位,小于等于就不进位。例如:

2.55.toFixed(1)

0   10000000000   0100011001100110011001100110011001100110011001100110
          - 01000000000000000000000000000000000000000000000000
          = 0000011001100110011001100110011001100110011001100110

然而   0000011001100110011001100110011001100110011001100110   即   0.000011001100110011001100110011001100110011001100110    =   0.04999999999999982236431605997495353221893310546875   <   2^-2=0.05

也就是说不会进位,实际上v8核心是通过尾数移位并通过某一个指定的标志位是否为1来判断进位的。

解决方法

百度上已经有许多封装好的成熟代码,基本围绕着重写  Number.prototype.toFixed( )  解决,本文不在赘述。

此处贴上一个觉得靠谱的toFixed( ) 重写文章: js toFixed失去精度问题


版权声明:本文提到的外链皆为原作者原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。

JS007. 深入探讨带浮点数运算丢失精度问题(二进制的浮点数存储方式)的更多相关文章

  1. JS 浮点数运算丢失精度解决方案

    除法 function accDiv(arg1,arg2){ var t1=0,t2=0,r1,r2; try{t1=arg1.toString().split(".")[1].l ...

  2. JavaScript浮点数运算的精度问题

    之前在做浮点数计算时,偶然发现计算结果有误差,度娘了解了下,补充整理了下. 误差是什么样子的呢?举例 console.log(0.1+0.2); // 0.30000000000000004 事实上在 ...

  3. 浮点数运算的精度问题:以js语言为例

    在 JavaScript 中整数和浮点数都属于 Number 数据类型,所有数字都是以 64 位浮点数形式储存,即便整数也是如此. 所以我们在打印 1.00 这样的浮点数的结果是 1 而非 1.00  ...

  4. JavaScript 浮点数运算的精度问题

    问题描述 在 JavaScript 中整数和浮点数都属于 Number 数据类型,所有数字都是以 64 位浮点数形式储存,即便整数也是如此. 所以我们在打印 1.00 这样的浮点数的结果是 1 而非 ...

  5. Java使用BigDecimal解决浮点型运算丢失精度的问题

    @Test public void test1(){ System.out.print(0.05+0.01); } @Test public void test2(){ BigDecimal b1 = ...

  6. Number浮点数运算详解

    文章来自我的 github 博客,包括技术输出和学习笔记,欢迎star. 一道题 0.1 + 0.2 = ? 在浏览器中测试下计算结果,得到的结果是 0.30000000000000004,并不是理想 ...

  7. js,java,浮点数运算错误及应对方法

    js,java浮点数运算错误及应对方法 一,浮点数为什么会有运算错误 IEEE 754 标准规定了计算机程序设计环境中的二进制和十进制的浮点数自述的交换.算术格式以及方法. 现有存储介质都是2进制.2 ...

  8. JavaScript 浮点数运算 精度问题

    JavaScript小数在做四则运算时,精度会丢失,这会在项目中引起诸多不便,先请看下面脚本. //加减 <script type="text/javascript" lan ...

  9. PHP浮点数运算精度造成的,订单金额支付经常少1分的问题

    最近碰见一个奇怪的问题,商城通过微信支付的订单经常少一分钱,经过排查是PHP浮点运算精度问题造成的 由PHP浮点数运算精度造成的,鸟哥的Bolg有详细的说明.http://www.laruence.c ...

随机推荐

  1. 跟你说个笑话,硕士毕业两年,月薪10k,天天面向CV编程

    "枯燥乏味的一天,又tm要开始了". 早上10:00,程序员毛毛带着路上买的早餐,打开24英寸的显示屏,去某论坛查一下昨天没有解决的bug. 9 个小时增删改查.搬砖写代码的一天又 ...

  2. 两万字长文,彻底搞懂Kafka!

    1.为什么有消息系统 1.解耦合 2.异步处理 例如电商平台,秒杀活动. 一般流程会分为: 风险控制 库存锁定 生成订单 短信通知 更新数据 通过消息系统将秒杀活动业务拆分开,将不急需处理的业务放在后 ...

  3. Go语言笔记[实现一个Web框架实战]——EzWeb框架(一)

    Go语言笔记[实现一个Web框架实战]--EzWeb框架(一) 一.Golang中的net/http标准库如何处理一个请求 func main() { http.HandleFunc("/& ...

  4. 跟我一起写 Makefile(十)

    四.foreach 函数 foreach函数和别的函数非常的不一样.因为这个函数是用来做循环用的,Makefile中的foreach函数几乎是仿照于Unix标准Shell(/bin/sh)中的for语 ...

  5. Linux进程理解与实践(四)wait函数处理僵尸进程

    Wait的背景 当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止) 子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程 ...

  6. 从官网下载历史版本的java

    下载历史版本的java 因为一些bug需要降低java版本来尝试解决,但是好多都要收费,我就搞不明白了,官网都有免费的我要你的收费软件干嘛 首先直接搜索java,进入Oracle,或者 Java SE ...

  7. BUUCTF刷题系列(1)5.25日记

    前面的题目都不太难,就直接从SQL注入开始了. 这个样子的话,明显就是注入,我们先拿出SQL语句:http://fb415201-6634-4fc3-a6bc-a67b84ea1ed2.node3.b ...

  8. Docker中安装了gitlab,忘记了管理员密码,进行管理员密码重置

    重置docker中gitlab中root账号的密码 一.进入Docker的gitlab容器中 1.查看所有容器 docker ps 2.进入gitlab容器中 docker exec -it gitl ...

  9. uwp Button的动态效果

    你应该覆盖Button样式 <Page.Resources> <Style TargetType="Button" x:Key="CustomButto ...

  10. Object 类中的主要结构

    == 操作符与equals 方法 == 操作符  equals 方法  重写equals() 方法的 toString()  方法