背景

之前在一个项目中,涉及到了金额,协议组定的标准是按照分的单位进行传递的,但是交互上,web页面中为了更友好的体验,是使用的元作为单位的,这个时候就需要转换一下单位

本来是很简单的一个转化的需求,在和后端联调的时候发现,保存的时候返回了参数错误,原因就是由于js浮点数精度带来的影响,导致保存的时候保存的位数特别多。

之前的开发过程中,对这个不精确的问题只是了解,有问题了就parseInt一下,但没有去细想过要怎么解决,所以今天整理了一下之后分享一下,先了解下原因,再看下怎么解决和规避

问题

输入金额 0.55,我传递之后应该乘 100 后下发,正常来说应该传的是55,但是实际上,由于精度丢失,最后的结果如下图所示:

那追根溯源,到底为什么会产生精度丢失的问题呢?

计算机底层只有0 和 1, 所以所有的运算最后实际上都是二进制运算。十进制整数利用辗转相除的方法可以准确地转换为二进制数,但浮点数呢?

先看下面一张图,是关于IEEE 754标准(IEEE二进位浮点数算术标准(IEEE Standard for Floating-Point Arithmetic)的标准编号):

这个标准是JS的浮点数的实现标准,大概解释一下这张图就是:

  • 第一位是符号位
  • 中间11位代表的是指数位
  • 最后的52位代表尾数位

也就是说,浮点数最终在运算的时候实际上是一个符合该标准的二进制数

我们可以看一个例子:

为了验证该例子,我们得先知道怎么将浮点数转换为二进制,整数我们可以用除2取余的方式,小数我们则可以用乘2取整的方式。

0.1转换为二进制:

  • 0.1 * 2,值为0.2,小数部分0.2,整数部分0
  • 0.2 * 2,值为0.4,小数部分0.4,整数部分0
  • 0.4 * 2,值为0.8,小数部分0.8,整数部分0
  • 0.8 * 2,值为1.6,小数部分0.6,整数部分1
  • 0.6 * 2,值为1.2,小数部分0.2,整数部分1
  • 0.2 * 2,值为0.4,小数部分0.4,整数部分0
  • 从0.2开始循环

0.2转换为二进制:

  • 可以直接参考上述,肯定最后也是一个循环的情况

所以最终我们能得到两个循环的二进制数:

0.1:0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1100 ...

0.2:0.0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 ...

这两个的和的二进制就是:

sum:0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 ...

所以最终我们只能得到和的近似值(按照IEEE 754标准保留 52位,按 0舍1入 来取值)

利用按权相加法,sum的十进制数则为:

sum ≈ 0.30000000000000004

这个例子说明了什么?

说明JS浮点数精度的缺失实际上是因为浮点数的小数部分无法用二进制很精准的转换出来,而以近似值来进行运算的话,肯定就存在精度的问题

解决

了解了真相之后,我们可以怎么处理呢?

我的项目中是直接parseInt了一下,因为误差很小,可以忽略不计。

但后来想想不能这么就放过去了,这种一刀切的方法太暴力了,万一涉及到需要特别精确的场景,这种方法会有问题。

所以,最好的办法还是需要找方法提高精度,直接规避。

思路其实非常简单,既然浮点数的情况下会丢失精度,那我们所有运算的时候都先小浮点数转换为整数,等计算完之后,再按比例转换会浮点数,这样就避免了再二进制十进制转换的时候计算机的精度问题。

比如上面的加法的例子,我们定义一个工具函数add:

const 

现在我们再来看看结果:

但有个问题,我们之前还有个例子,0.55在乘的时候就会产生精度问题,所以这里我们再优化一下,把一个数变成整数,是不是也可以理解为将其变成字符串后把小数点去掉再转回数字,这样效果和相乘的效果不是一样的吗:

const 

这样就解决了。

当然,这只是考虑了最简单的情况,比如如果位数不同还要特殊处理下。不过只要思路有了,后续的就属于添砖加瓦了,考虑得很全面的话,可以考虑封装成一个库,这篇文章就权当抛砖引玉吧。

ieee754浮点数转换工具_关于JS浮点数运算不精确的原因和解决方案相关推荐

  1. 时间戳转换工具java_时间戳转换_时间戳转换工具_时间戳转换成时间日期_55查询...

    时间戳转换工具支持的时间格式 2021-03-02 2021年03月02日 2021-03-02 07:29:08 2021年03月02日 07:29:08 2021年03月02日 07点29分08秒 ...

  2. mysql时间和时间戳转换工具_时间戳转换工具

    时间戳转换工具支持的时间格式 2021-02-03 2021年2月03日 2021-02-03 09:18:17 2021年2月03日 09:18:17 2021年2月03日 09点18分17秒 只输 ...

  3. verilog 浮点数转定点数_定点数转浮点数verilog

    本文目的是记录学习<数字信号处理的FPGA实现>过程中,用verilog语言实现简单的定点数到浮点数转换的经历. 若以f[31:0]表示一个单精度32位浮点数,f[31]是符号位,其为'0 ...

  4. gbk编码在线转换工具_珍藏的4个PDF格式转换网站「在线工具,无需下载,还免费哦。」...

    PDF文件相信大家并不陌生,我们经常在工作中都会收到客户.同事.老板发来这种PDF文件,这些文件往往都会记录着一些产品的详细介绍与说明.但是PDF并不是那么好编辑的,我们通常都会将PDF转换成Offi ...

  5. java 进制转换工具_进制转换工具(JAVA)

    /**进制转换工具,支持2-36任意进制间相互转换 */ public class HexConverter { public static String Quotient = null; publi ...

  6. ios dat 文件读写_Xilisoft iPad Magic Platinum for Mac(ios设备文件传输和转换工具)_资源共享论坛...

    Xilisoft iPad Magic Platinum for Mac是一款ios设备文件传输和转换工具,可以帮助用户将Mac上的应用程序,电影和音乐放到iPad上,无需iTunes即可将iPad应 ...

  7. oracle 查询变换器,万能数据库转换工具_新诚软数据转换器 V1.4 免费版

    您还在为数据在各个数据库之间转换而烦恼吗?<新诚软数据转换器>是一个万能数据库转换工具,这个数据库转换工具可以为Oracle.SQL Server.Access.DB2.InterBase ...

  8. 助记词转换工具_有助于大流行的10种翻译工具

    助记词转换工具 With social distancing to keep us at arm's length from strangers, no traveling, and a scarci ...

  9. javaheapspace解决方案_高手总结的9种 OOM 常见原因及解决方案

    当 JVM 内存严重不足时,就会抛出 java.lang.OutOfMemoryError 错误.本文总结了常见的 OOM 原因及其解决方法,如下图所示.如有遗漏或错误,欢迎补充指正. 1.Java ...

最新文章

  1. 分页请求json数据_pyspider抓取虎嗅网文章数据
  2. .NET Core实践系列之SSO-跨域实现
  3. 《STL源码剖析》相关面试题总结
  4. NVIDIA ECCV18论文:超像素采样网络助力语义分割与光流估计(代码将开源)
  5. Unix NetWork Programming——环境搭建(解决unp.h等源码编译问题)(转载)
  6. 变分模态分解(VMD)原理-附代码
  7. SQL Server 时间、日期函数
  8. 亲身体验过13款滚动截屏App,谁才是最好用的iPhone长截屏工具?
  9. Opening My World——ESRI用户大会有感
  10. Visual Studio安装指南
  11. 4种网游外挂制作方法
  12. Android studio @Author的使用以及TAG的自动生成
  13. Linux CPU使用率超过100%的原因
  14. mysql数据库生成脚本工具下载_PHPMaker下载-基于MYSQL数据库自动生成PHP脚本的软件 v2019.0.2.2 官方版 - 安下载...
  15. Electron-开发第一个桌面应用
  16. Linova and Kingdom
  17. python小程序嵌入excel_用原生的方式操作Excel,Python玩转Excel神器xlsxwriter详解!...
  18. SAR+L波段+森林生物量估计+高度反演
  19. 高数--函数--初等函数
  20. android l m8,HTC M8或于10月份升级Android L

热门文章

  1. go 接口 构造器_Go 中接口值的复制
  2. discuz search.php修改,discuz程序如何将热门搜索修改为指向门户搜索的方法
  3. C语言 BMP24位变单色,怎么将24位色BMP图片改为单色或16色?(2)
  4. xml转svg_C# Excel 转PDF/图片/HTML/TXT/XML/XPS/CSV/ODS/SVG/EMF
  5. windows下caffe+CPUOnly实现MNIST手写分类
  6. ProxyChains
  7. java2实用教程知识点_Java2实用教程(第5版)重要点及遗漏点(三)
  8. 在计算机网络中发送电子邮件遵循的协议是,一、计算机网络刷题
  9. 现代程序设计 作业4
  10. 小孔成像实验探究的软件_探究小孔成像实验报告.doc