×

js字符串转数字精度丢失

js字符串转数字精度丢失(javascript 整数加减会有精度丢失吗)

admin admin 发表于2024-02-26 03:33:19 浏览33 评论0

抢沙发发表评论

“js字符串转数字精度丢失”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看js字符串转数字精度丢失(javascript 整数加减会有精度丢失吗)!

本文目录

javascript 整数加减会有精度丢失吗

你试试看 0.1 + 0.7,也是一样有精度丢失的例如 0.1 + 0.1,在 JS 下用直接输出是 0.2,然而这只是因为默认情况下直接输出的话是有 17 位小数的,然而误差出现在 17 位小数之后。。。0.1 + 0.1 在 20 位小数的情况下是 0.20000000000000001110-

JavaScript为什么浮点数会丢失精度

JS浮点计算问题

问题

用js进行浮点数计算,结果可能会“超出预期”,大部分计算结果还是对的,但是我们可不想在计算这么严谨的事情上还有意外的惊喜。比如:

  • 0.3 + 0.6 = 0.8999999999999999

  • 0.3 - 0.2 = 0.09999999999999998

  • 0.3 * 1.5 = 0.44999999999999996

  • 0.3 / 0.1 = 2.9999999999999996

  • 看完这几个计算结果,如果你没用过js,你可能会有点崩溃。我只能说,这就是js的魅力所在。

    分析

    在这之前,你需要知道以下几点:

  • js中数字类型只有Number;

  • js的Number是IEEE 754标准的64-bits的双精度数值

  • 网上有很多关于此问题的解释,由于计算机是用二进制来存储和处理数字,不能精确表示浮点数,而js中没有相应的封装类来处理浮点数运算,直接计算会导致运算精度丢失。其实高级语言(c#,java)也存在此问题,只不过它们自己内部做了处理,把这种精度差异给屏蔽掉了。有些小数转换为二进制位数是无穷的(有循环),但是64位中小数最多只有52位,因此对于位数超过的相当于被截取了,导致了精度的丢失。这个地址可以用来浮点数和IEEE 754标准的64-bits的互转(背后是二进制的转换),用这个我们来验证下0.3-0.2。

  • 0.3转换后为0.299999999999999988897769753748

  • 0.2转换后为0.200000000000000011102230246252

  • 0.299999999999999988897769753748-0.200000000000000011102230246252=0.099999999999999977795539507496

  • 这和js直接计算的结果0.09999999999999998想吻合。

    分析下来,终于明白并不是js自身发育不良,只是没有及时补充营养,我们只能另想出路了。

以上是网上找的

我以前遇到过问题2中浏览器计算的结果 是两种,所以和浏览器也有问题

JS位运算异常(位运算精度丢失)的原因探究

《【转+补充】深入研究js中的位运算及用法》 《【JS时间戳】获取时间戳的最快方式探究》

日常开发中一直没遇到过位运算导致精度丢失的问题,直到这天,搞10位时间戳取整的时候,终于被我撞上了。具体是个什么场景呢,我们来还原下案发现场:

可以看到输出的结果为:

得到的 t 是一个精确到微秒的时间戳。但是请求接口的时候需要的是一个10位(精确到秒)的时间戳,所以这里需要将它转换为10位,自然就是 1000 即可,然后通过位运算来实现类似 Math.trunc 的取证效果,得到了我们要的10位时间戳。至此完美解决!那问题又是如何发生的呢?

按照上面的运算规律,如果我们要获取13位时间戳,是不是直接对 t》》0 就可以了呢?我们来看一下:

输出结果如下:

WTF!!!看到了咩!!!居然输出了一个负数!!!我们想要的结果应该是 1597113682985 才对啊!为什么会出现了负数呢!!!

由此,怪物出现啦!我们今天就来解读(xiang fu)一下它!

想到这里,我们一定就会怪是位运算的锅!那这个锅该怎么让位运算背起来呢!我们来研究一下!

首先我们知道,JS中没有真正的整型,数据都是以double(64bit)的标准格式存储的,这里就不再赘述了,要想搞透其中的原理,请打开 【传送门】

位运算是在数字底层(即表示数字的 32 个数位)进行运算的。由于位运算是低级的运算操作,所以速度往往也是最快的(相对其它运算如加减乘除来说),并且借助位运算有时我们还能实现更简单的程序逻辑,缺点是很不直观,许多场合不能够使用。

以下来源于w3shool: ECMAScript 整数有两种类型,即有符号整数(允许用正数和负数)和无符号整数(只允许用正数)。 在 ECMAScript 中,所有整数字面量默认都是有符号整数 ,这意味着什么呢?

有符号整数使用 31 位表示整数的数值,用第 32 位表示整数的符号,0 表示正数,1 表示负数。数值范围从 -2147483648 到 2147483647 。

可以以两种不同的方式存储二进制形式的有符号整数,一种用于存储正数,一种用于存储负数。 正数是以真二进制形式存储的 ,前 31 位中的每一位都表示 2 的幂,从第 1 位(位 0)开始,表示 20,第 2 位(位 1)表示 21。没用到的位用 0 填充,即忽略不计。例如,下图展示的是数 18 的表示法。

那在js中二进制和十进制如何转换呢?如下

负数同样以二进制存储,但使用的格式是二进制补码。计算一个数值的二进制补码,需要经过下列3个步骤:

例如,要确定-18的二进制表示,首先必须得到18的二进制表示,如下所示: 0000 0000 0000 0000 0000 0000 0001 0010

接下来,计算二进制反码,如下所示: 1111 1111 1111 1111 1111 1111 1110 1101

最后,在二进制反码上加 1,如下所示: 1111 1111 1111 1111 1111 1111 1110 1101 + 0000000000000000000000000000 0001 = 1111 1111 1111 1111 1111 1111 1110 1110

因此,-18 的二进制就是 1111 1111 1111 1111 1111 1111 1110 1110 而其相反数18的二进制为 0000 0000 0000 0000 0000 0000 0001 0010

ECMAScript会尽力向我们隐藏所有这些信息,在以二进制字符串形式输出一个负数时,我们看到的只是这个负数绝对值的二进制码前面加上了一个负号

JavaScript 只有一种数字类型 ( Number )

我们将 1596596596.3742654.toString(2) 转为二进制字符串表示如下: 1011111001010100010000101110100.0101111111001111110111 但实际在内存中的存储如下:

说到这里就不得不简单提一下数字精度丢失的问题。上面也知道,JS中所有的数字都是用double方式进行存储的,所以必然会存在精度丢失问题。

以下转自文章: JavaScript数字精度丢失问题总结

此时只能模仿十进制进行四舍五入了,但是二进制只有 0 和 1 两个,于是变为 0 舍 1 入。这即是计算机中部分浮点数运算时出现误差,丢失精度的根本原因。

大整数的精度丢失和浮点数本质上是一样的,尾数位最大是 52 位,因此 JS 中能精准表示的最大整数是 Math.pow(2, 53) ,十进制即 9007199254740992

大于 9007199254740992 的可能会丢失精度: 9007199254740992 》》 10000000000000...000 ``// 共计 53 个 0 9007199254740992 + 1 》》 10000000000000...001 ``// 中间 52 个 0 9007199254740992 + 2 》》 10000000000000...010 ``// 中间 51 个 0

实际上 9007199254740992 + 1 ``// 丢失 9007199254740992 + 2 ``// 未丢失 9007199254740992 + 3 ``// 丢失 9007199254740992 + 4 ``// 未丢失

以上,可以知道看似有穷的数字, 在计算机的二进制表示里却是无穷的,由于存储位数限制因此存在“舍去”,精度丢失就发生了。

想了解更深入的分析可以看这篇论文(你品!你细品!): What Every Computer Scientist Should Know About Floating-Point Arithmetic 关于精度和范围的内容可查看 【JS的数值精度和数值范围】

通过前面的知识补充,我们已经知道:

这也就是为什么对于整数部位为10位的时间戳,通过位运算可以进行取整(因为目前时间戳159xxxxxxx《2147483647),不存在时间戳超过范围的问题。但是对于13位时间戳,如 1596615447123》2147483647 ,此时再通过位运算操作的时候就会导致异常,如:

这主要是因为在进行位运算之前,JS会先将64bit的浮点数 1596615447015.01 转为32bit的有符号整型后进行运算的,这个转换过程如下:

为了验证上述过程,我们再举一个例子: 1590015447015.123 》》 0 = 877547495

将将将将!没错的吧!所以JS的这个坑还真是。。。 让人Orz

js中数字100不等于100怎么回事

精度丢失问题。js中,数字类型运算都需要先将十进制转二进制,但小数点后的位数转二进制会出现无限循环的问题,只能舍0入1,所以会出现精度丢失问题,100不等于100。JavaScript,简称JS,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。

JS的计算时精度丢失问题

如:0.1+0.2 !== 0.3;0.1*0.2 !== 0.03; 如:9999999999999999 === 10000000000000001; 如:1.335.toFixed(2) // 1.33;1.336.toFixed(2) // 1.34; 二进制模仿十进制进行四舍五入,而二进制只有0和1,于是就0舍1入,于是就导致了小数计算不精确。大数的精度丢失本质上是和小数一样,js中表示最大的数是Math.pow(2, 53),十进制即 9007199254740992;大于该数的值可能会丢失精度。 小数的话,一般转成整数进行计算,然后对结果做除法;同样也可以直接对结果进行4舍5入; 对于大数出现的问题概率较低,毕竟还要运算结果不超过最大数就不会丢失精度; javaScript数字精度丢失问题总结 js中精度问题以及解决方案 JavaScript 中精度问题以及解决方案

js哪些运算精度丢失

由于在H5页面上需要进行动态的金额计算,且金额涉及到了小数,因而随之产生了JS浮点数计算的精度丢失问题。 刚开始的时候,测试给提了一个金额计算误差的问题,刚开始我还没怎么重视,然后瞅了瞅代码,随便改了改做了些异常处理,然后就给提交了。 接着,测试又提了一个bug,“6.8-0.9=5.8”。然后顿时我就蒙逼了,随后突然意识到,JS作为解释性语言,直接计算会有浮点数精度丢失问题。接下来,在网上找了一些资料,然后也根据具体的原理自己做了一些修改,最终解决了问题。浮点数的二进制表示:IEEE 754 标准是IEEE二进位浮点数算术标准(IEEE Standard for Floating-Point Arithmetic)的标准编号,等同于国际标准ISO/IEC/IEEE 60559。该标准由美国电气电子工程师学会(IEEE)计算机学会旗下的微处理器标准委员会(Microprocessor Standards Committee, MSC)发布。这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number),一些特殊数值(无穷(Inf)与非数值(NaN)),以及这些数值的「浮点数运算子」;它也指明了四种数值修约规则和五种例外状况(包括例外发生的时机与处理方式)。JS的浮点数实现也是遵循IEEE 754标准,采用双精度存储(double precision),进行了相关的实现。其中1位用来表示符号位,11位用来表示指数,52位表示尾数。解决方案:本质上在处理这类问题的时候,基本的思路就是通过将浮点数转换成整数进行计算,然后再将整数的小数点位调整,转回正确的浮点数结果。

数字字符串转换为数字的精度丢失问题.

p += p*10 + float(s - ’0’); 改为p = p*10 + float(s - ’0’);

js parsefloat 精度丢失

JS 只支持 16 位以下的数值,更大的数精度完全没有保证(在这个范围里的还经常有问题呢)……P.S. JS 压根就不适合做高精度的浮点运算,何况题主这个都小数点后 14 位了。

关于js中小数运算丢失精度的处理办法

浮点数值的最高精度是17位小数,但在进行运算的时候其精确度却远远不如整数;整数在进行运算的时候都会转成10进制; 而java和JavaScript中计算小数运算时,都会先将十进制的小数换算到对应的二进制,一部分小数并不能完整的换算为二进制,这里就出现了第一次的误差。待小数都换算为二进制后,再进行二进制间的运算,得到二进制结果。然后再将二进制结果换算为十进制,这里通常会出现第二次的误差。 所以(0.1+0.2)!=03 解决这种问题,可以将小数变成整数进行运算,然后再将结果变为小数。 //乘法 function multiNum (a,b){   var c = 0, d = a.toString(), e = b.toString(); try {       c += d.split(".").length; } catch (f) { }   try {       c += e.split(".").length; } catch (f) { }   return Number(d.replace(".","")) * Number(e.replace(".","")) / Math.pow(10,c); } //除法 function divide (a,b){   var c,d,e = 0, f = 0; try {       e = a.toString().split(".").length; } catch (g) { }   try {       f = b.toString().split(".").length; } catch (g) { }   return c = Number(a.toString().replace(".","")),d = Number(b.toString().replace(".","")),this.mul(c / d,Math.pow(10,f - e)); } //加法 function addNum (a,b){   var c,d,e; try {       c = a.toString().split(".").length; } catch (f) {       c = 0; }   try {       d = b.toString().split(".").length; } catch (f) {       d = 0; }   return e = Math.pow(10,Math.max(c,d)),(multiNum(a,e) + multiNum(b,e)) / e; } //减法 function subNum (a,b) {   var c,d,e; try {       c = a.toString().split(".").length; } catch (f) {       c = 0; }   try {       d = b.toString().split(".").length; } catch (f) {       d = 0; }   return e = Math.pow(10,Math.max(c,d)),(multiNum(a,e) - multiNum(b,e)) / e; }

关于js字符串转数字精度丢失,javascript 整数加减会有精度丢失吗的介绍到此结束,希望对大家有所帮助。