资讯专栏INFORMATION COLUMN

Javascipt中精确小数运算的实现

notebin / 2113人阅读

摘要:但由于十进制小数并不总能用二进制小数精确表示,在进行小数运算时,经常会出现莫明其妙的误差,比如之类的。它唯一能解决的问题就是避免十进制小数和二进制小数之间的转换误差它不能提高运算的精度有效数字,也不能扩大数字的表示范围。

以前的旧文,貌似还是挺有用的,在这里记一下避免丢失:

基于Web的应用程序,经常需要在页面中作些简单的计算,用作数据提交前的验证,或者给用户提供更友好的信息。但由于十进制小数并不总能用二进制小数精确表示,在进行小数运算时,经常会出现“莫明其妙”的误差,比如“33*2.46=81.179999999999999”之类的。如果要在页面上显示计算结果,特别是当这个结果表示金额的时候,误差通常是不可容忍的。

网上有人说Javasript不能做精确运算,所以会出现误差云云。这当然是不对的,这种情况应该是由计算机二进制表示的本质决定的。应该说,Javascript的表现其实还好一些,因为在数字进行运算之前,我们总是可以得到它的精确表示(字符串)。

解决问题的基本思路就是牺牲速度换精度,逐位进行运算,并且自己在程序逻辑中实现进位。为此,Java提供了BigDecimal类。而在Javascript中,我们就没这么幸运了,没有现成的类库可供使用。可能是制订规范的人也认为没必要使用JS来做“科学计算”吧。

我以前做的项目中,经常会碰到计算金额总价、合计、总计之类的“商业计算”,对精确小数运算的需求还是比较迫切的,所以自己开发了一个小数运算的“类”。实现这个类的时候,使用了投机取巧的办法:把小数转换为整数,运算完成后,再转换回去。它唯一能解决的问题就是:避免十进制小数和二进制小数之间的转换误差;它不能提高运算的精度(有效数字),也不能扩大数字的表示范围。
使用方法如下:

//使用数字的literal表示,创建一个Decimal对象    
var d1 = new Decimal(3.68);    
//调用该对象的四则运算方法,得到一个新的Decimal对象   
var res=d1.add(2.25);    
//调用该对象的valueOf方法,得到数值   
alert( res.valueOf() ); //显示 5.93    
//或者调用该对象的toString方法,得到数值的字符串表示   
alert( res.toString() ); //显示 5.93    
  
//可用的运算方法对应四则运算的+、-、×、÷   
var d1 = new Decimal(3.68);   
var res=d1.add(2.25);   
assertEquals("3.68+2.25", "5.93", res.toString());   
  
var d1 = new Decimal(3.68);   
var res=d1.minus(2.25);   
assertEquals("3.68-2.25", "1.43", res.toString());   
  
var d1 = new Decimal(2.22);   
var res=d1.multiply(3.33);   
assertEquals("2.22*3.33", 7.3926, res.valueOf());   
  
var d1 = new Decimal(6.66);   
var res=d1.divide(2.22);   
assertEquals("6.66/2.22", 3, res.valueOf());  

源码在这里下载:https://pan.baidu.com/s/1i4Gugqp

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81665.html

相关文章

  • 高精度数学运算

    摘要:使用,保证精度的同时,能精准的进行四舍六入计算。类精确的数学运算使用来实现精准度因为精度的原因构造方法的结果有一定的不可预知性,例如因此建议使用。算法规则四舍六入五考虑,五后非零就进一,五后皆零看奇偶,五前为偶应舍去,五前为奇要进一。 四舍六入计算 算法规则: 四舍六入五考虑, 五后非零就进一, 五后皆零看奇偶, 五前为偶应舍去, 五前为奇要进一。 使用BigDecimal,保证精度的...

    liaosilzu2007 评论0 收藏0
  • JS魔法堂:彻底理解0.1 + 0.2 === 0.30000000000000004背后

    摘要:也就是说不仅是会产生这种问题,只要是采用的浮点数编码方式来表示浮点数时,则会产生这类问题。到这里我们都理解只要采取的浮点数编码的语言均会出现上述问题,只是它们的标准类库已经为我们提供了解决方案而已。 Brief 一天有个朋友问我JS中计算0.7 * 180怎么会等于125.99999999998,坑也太多了吧!那时我猜测是二进制表示数值时发生round-off error所导致,但并不...

    JerryWangSAP 评论0 收藏0
  • 带你入门 JavaScript ES6 (二)

    摘要:上一篇学习下一代语法一,我们学习了关于块作用域变量或常量声明和语法新的字符串拼接语法模版字面量数组元素或对象元素的解构赋值和对象字面量简写的相关知识。这便是扩展运算符的用途之一。 本文同步 带你入门 JavaScript ES6 (二),转载请注明出处。 上一篇学习下一代 JavaScript 语法: ES6 (一),我们学习了关于块作用域变量或常量声明 let 和 const 语法、...

    chanthuang 评论0 收藏0
  • JS数值

    摘要:由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心。根据标准,位浮点数的指数部分的长度是个二进制位,意味着指数部分的最大值是的次方减。也就是说,位浮点数的指数部分的值最大为。 一 前言 这篇文章主要解决以下三个问题: 问题1:浮点数计算精确度的问题 0.1 + 0.2; //0.30000000000000004 0.1 + 0.2 === 0.3; // ...

    williamwen1986 评论0 收藏0
  • JS如何理解浮点数?

    摘要:本文通过介绍的二进制存储标准来理解浮点数运算精度问题,和理解对象的等属性值是如何取值的,最后介绍了一些常用的浮点数精度运算解决方案。浮点数精度运算解决方案关于浮点数运算精度丢失的问题,不同场景可以有不同的解决方案。 本文由云+社区发表 相信大家在平常的 JavaScript 开发中,都有遇到过浮点数运算精度误差的问题,比如 console.log(0.1+0.2===0.3)// fa...

    bang590 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<