浅谈JavaScript中小数和大整数的精度丢失.

合集下载

java,js中小数计算精度误差问题

java,js中小数计算精度误差问题

java,js中⼩数计算精度误差问题 在碰见这个问题之前我完全没有这个概念,碰见了特此记录; 项⽬js⾥⾯中⽤到了number*0.2(其中number是⼀个整数,我测试的时候是259),得到的结果却是51.80000000000000004这么个结果, 当时直接蒙逼,根本不知道什么原因,随⼿在java中写了⼀个System.out.println(259*0.2),得到⼀样的结果; 这个时候觉得就不是数据类型的问题了,上⽹围观⼤神给出的原因--------------------------------------------------------------------------------------------------------------------------------------------------- ⽹上有这样⼀个问题:0.1+0.2在计算机中的结果 不论java,javascript,python中的结果都是0.30000000000000004计算机中存储的都是⼆进制的0和1,⽽我们现实中的数存⼊计算机中转换为⼆进制时有可能不能整除,也就是不能正好整除,所以⽤⼆进制表⽰现实中的数并计算就产⽣了误差。

把⼗进制的0.1和0.2转换为⼆进制:0.1 => 0.0001 1001 1001 1001…(1001⽆限循环)0.2 => 0.0011 0011 0011 0011…(0011⽆限循环)但是我们计算机的硬件存储的位数是有限制的不可能⽆限循环下去,⼀般双精度浮点数总共占⽤64位,、其中最多53位为有效精度数字(包括符号位),所以存储时:0.1=>0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 10010.2=>0.0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 00110.1+0.2=>0.0100 1100 1100 1100 1100 1100 11001 100 1100 1100 1100 1100 1100转换为⼗进制就是:0.30000000000000004。

浅谈JavaScript中小数和大整数的精度丢失

浅谈JavaScript中小数和大整数的精度丢失

下面小编就为大家带来一篇浅谈JavaScript中小数和大整数的精度丢失。

小编觉得挺不错的,现在就分享给大家,也给大家做个参考。

先来看两个问题:0.1 + 0.2 == 0.3; // false9999999999999999 == 10000000000000000; // true第一个问题是小数的精度问题,在业界不少博客里已有讨论。

第二个问题,去年公司有个系统的数据库在做数据订正时,发现有部分数据重复的诡异现象。

本文将从规范出发,对上十进制0.1 的二进制为0.0 0011 0011 0011 …(循环0011)十进制0.2 的二进制为0.0011 0011 0011 …(循环0011)0.1 + 0.2 相加可表示为:   e = -4; m = 1.10011001100...1100(52 位) + e = -3; m = 1.10011001100...1100(52 位)---------------------------------------------   e = -3; m = 0.11001100110 (0110) + e = -3; m = 1.10011001100 (1100)---------------------------------------------   e = -3; m = 10.01100110011 (001)--------------------------------------------- = 0.01001100110011 (001) = 0.30000000000000004(十进制)根据上面的演算,还可以得出一个结论:当十进制小数的二进制表示的有限数字不超过52 位时,在JavaScript 里是可以精确存储的。

js 精度丢失 原理

js 精度丢失 原理

js 精度丢失原理
JS中精度丢失的原理主要有以下几个方面:
1. 浮点数的表示精度有限:在JS中,基本数据类型Number使用的是双精度浮点型,也就是其他语言中的double类型。

这种数据类型在内存中是以一定的位数来存储的,由于表示精度有限,对于某些无法精确表示的十进制小数,计算机在将其转换为二进制小数时会存在舍入误差,导致精度丢失。

2. 舍入误差的累积:在进行一系列浮点数算术运算时,舍入误差可能会累积并导致精度丢失。

每一次运算都会引入一些误差,这些误差在多次运算中逐渐累积,导致最终结果的精度降低。

3. 比较运算的不精确性:由于浮点数的表示精度有限,直接比较浮点数可能会导致不准确的结果。

微小的舍入误差可能使得两个看似相等的浮点数在比较时被认为是不等的。

4. 数值范围的限制:浮点数的表示范围是有限的,超出范围的数值可能会导致溢出或下溢,进而影响计算结果的精度。

了解JS中精度丢失的原理有助于更好地理解和解决相关问题,特别是在进行高精度计算或处理金融数据时尤为重要。

关于javascript小数精度丢失的完美解决方法介绍

关于javascript小数精度丢失的完美解决方法介绍

关于javascript小数精度丢失的完美解决方法介绍原因:js按照2进制来处理小数的加减乘除,在arg1的基础上将arg2的精度进行扩展或逆扩展匹配,所以会出现如下情况.javascript(js)的小数点加减乘除问题,是一个js的bug如0.3*1=0.2999999999等,下面列出可以完美求出相应精度的四种js 算法functionaccDiv(arg1,arg2){vart1=0,t2=0,r1,r2;try{t1=arg1.to String().split(".")[1].length}catch(e){}try{t2=arg2.toString().split(". ")[1].length}catch(e){}with(Math){r1=Number(arg1.toString().repl ace(".",""))r2=Number(arg2.toString().replace(".",""))returnaccMu l((r1/r2),pow(10,t2-t1));}}//乘法functionaccMul(arg1,arg2){varm=0,s1=arg1.toString(),s2=arg2.t oString();try{m+=s1.split(".")[1].length}catch(e){}try{m+=s2.split( ".")[1].length}catch(e){}returnNumber(s1.replace(".",""))*Number( s2.replace(".",""))/Math.pow(10,m)}//加法functionaccAdd(arg1,arg2){varr1,r2,m;try{r1=arg1.toString().split (".")[1].length}catch(e){r1=0}try{r2=arg2.toString().split(".")[1].len gth}catch(e){r2=0}m=Math.pow(10,Math.max(r1,r2))return(arg1* m+arg2*m)/m}//减法functionSubtr(arg1,arg2){varr1,r2,m,n;try{r1=arg1.toString().split (".")[1].length}catch(e){r1=0}try{r2=arg2.toString().split(".")[1].len gth}catch(e){r2=0}m=Math.pow(10,Math.max(r1,r2));n=(r1>=r2) r1:r2;return((arg1*m-arg2*m)/m).toFixed(n);}以上这篇javascript小数精度丢失的完美解决方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。

JS加减乘除精度丢失问题解决

JS加减乘除精度丢失问题解决

JS加减乘除精度丢失问题解决⼀、前⾔⼯作中经常遇到⽤户输⼊后在前端实时计算结果,⽐如输⼊单价和数量后⾃动计算总价,部分情况下会出现丢失精度的问题。

解决⽅式为将⼩数放⼤为整数,计算完后再缩⼩。

⼆、解决/** 加法* add(0.123 , 1.4567 , 10.56789)*/function add(...val) {let sum = 0,maxDecimalLength = getMaxDecimalLength(...val)val.forEach((x, index) => {// 所有数值转为整数计算sum += Math.round(x * Math.pow(10, maxDecimalLength))})return sum / Math.pow(10, maxDecimalLength)}/** 减法* subtract(0.123 , 1.4567 , 10.56789)*/function subtract(...val) {let sum,maxDecimalLength = getMaxDecimalLength(...val)val.forEach((x, index) => {let nurVal = Math.round(x * Math.pow(10, maxDecimalLength));if (index === 0)sum = nurValelsesum -= nurVal})return sum / Math.pow(10, maxDecimalLength)}/** 乘法* multiply(0.123 , 1.4567 , 10.56789)*/function multiply(...val) {let sum,decimalLengthSum = 0val.forEach((x, index) => {// 获取当前⼩数位长度let decimalLength = getMaxDecimalLength(x)// 将当前数变为整数let nurVal = Math.round(x * Math.pow(10, decimalLength));decimalLengthSum += decimalLengthif (index === 0)sum = nurValelsesum *= nurVal})return sum / Math.pow(10, decimalLengthSum)}/** 除法* divide(0.123 , 1.4567 , 10.56789)*/function divide(...val) {let sum = 0,decimalLengthSum = 0val.forEach((x, index) => {// 获取当前⼩数位长度let decimalLength = getMaxDecimalLength(x)// 将当前数变为整数let nurVal = Math.round(x * Math.pow(10, decimalLength)); if (index === 0) {decimalLengthSum = decimalLengthsum = nurVal} else {decimalLengthSum -= decimalLengthsum /= nurVal}})return sum / Math.pow(10, decimalLengthSum)}/** 获取⼩数位数*/function getMaxDecimalLength(...val) {// 最⼤⼩数位长度let maxDecimalLength = 0val.forEach((x) => {const strVal = x.toString(),dotIndex = strVal.indexOf('.')if (dotIndex > -1) {// 获取当前值⼩数位长度let curDecimalLength = strVal.length - 1 - dotIndexif (curDecimalLength > maxDecimalLength) {maxDecimalLength = curDecimalLength}}})return maxDecimalLength}。

js计算精度丢失的解决方法

js计算精度丢失的解决方法

js计算精度丢失的解决方法嘿,朋友们!咱今儿来聊聊 js 计算精度丢失这档子事儿。

你说这玩意儿就跟那调皮的小猴子似的,时不时就蹦出来给你捣捣乱。

咱先搞清楚为啥会有这情况呀。

就好比你要把一块大蛋糕切成好多好多小块,这中间难免就会有些误差嘛。

js 在处理一些小数计算的时候,就可能会出现这种类似的小偏差。

那咋解决呢?嘿,这就有招儿啦!咱可以用一些巧妙的方法来对付它。

比如说,咱可以把小数转化成整数来计算呀,就像你把那小蛋糕先整个儿的算好了,再去分小块,这样不就减少误差啦?或者呢,咱可以用一些专门的库,就像是给咱的计算找了个厉害的助手,让它来帮忙搞定那些容易出问题的地方。

你想想看呀,如果咱不解决这个问题,那可就麻烦啦!就好比你要去买东西,本来应该给人家十块钱,结果因为计算精度丢失,你给了人家九块九或者十块一,那多不合适呀!这要是在一些重要的场合,比如涉及到钱财交易或者数据统计啥的,那可不得了!咱还可以通过一些小技巧来检查和发现这些问题呢。

就像医生给病人做检查一样,得找到病根儿才能对症下药呀。

比如说,咱可以在计算前后对比一下结果,看看是不是有啥不对劲的地方。

还有啊,咱得养成一个好习惯,就是对计算结果要多留个心眼儿。

别一股脑儿就相信了,得好好琢磨琢磨,看看是不是合理。

这就好比你走路,得时不时瞅瞅脚下,别一不小心踩坑里啦!总之呢,解决 js 计算精度丢失这个问题,就像是给咱的代码世界打扫卫生,把那些脏东西都清理掉,让咱的程序跑得更顺畅,更准确。

咱可不能小瞧了这个事儿,得认真对待,不然它可会给咱惹出大麻烦的哟!你说是不是这个理儿呀?所以呀,咱可得把这些方法都记住,遇到问题就拿出来用,让咱的代码变得乖乖的,不再捣乱啦!。

Js四则运算精度问题处理

Js四则运算精度问题处理

Js四则运算精度问题处理JavaScript⼩数在做四则运算时,精度会丢失,这会在项⽬中引起诸多不便。

先看个具体的例⼦://较⼩的数运算console.log(0.09999999 + 0.00000001); //0.09999999999999999console.log(-0.09999999 - 0.00000001); //-0.09999999999999999console.log(0.012345 * 0.000001); //1.2344999999999999e-8console.log(0.000001 / 0.0001); //0.009999999999999998//较⼤的数运算console.log(999999999 * 111111111); //111111110888888900从上⾯的结果可以看出,都不是正确的。

为了解决浮点数运算不准确的问题,在运算前我们把参加运算的数先升级(10的X的次⽅)到整数,等运算完后再降级(0.1的X的次⽅)。

具体的操作如下:/*** 四则运算** @param x* @param y* @param op 操作符,0:加;1:减;2:乘;3:除* @param acc 保留⼩数位个数,进⾏四舍五⼊*/function execute(x, y, op, acc) {var xx = Number(x == undefined ? 0 : x);var yy = Number(y == undefined ? 0 : y);//var a = science(xx);var b = science(yy);var na = a.r1;var nb = b.r1;var ta = a.r2;var tb = b.r2;var maxt = Math.max(ta, tb);//精度值处理var result = 0;switch (parseInt(op, 10)) {case0: //加result = (xx * maxt + yy * maxt) / maxt;break;case1: //减result = (xx * maxt - yy * maxt) / maxt;break;case2: // 乘result = na * nb / (ta * tb);break;case3: // 除result = na / nb * (tb / ta);default:}//⼩数位数处理if (acc) {return Number(Number(result).toFixed(parseInt(acc)));} else {return Number(result);}}/*** 将数值升级(10的X的次⽅)到整数*/function science(num) {var re = {r1: 0, //数字去掉⼩数点后的值,也就是 r1*r2 的结果r2: 1//⼩数部分,10的长度次幂};if (isInteger(num)) { //整数直接返回re.r1 = num;return re;}var snum = scienceNum(num + ""); //处理0.123e-10类似问题var dotPos = snum.indexOf("."); //⼩数点位置var len = snum.substr(dotPos + 1).length; //⼩数点长度re.r2 = Math.pow(10, len);re.r1 = parseInt(snum.replace(".", ""));return re;}/*** 将数值转为字符串** 通过移动⼩数点扩⼤倍数或缩⼩倍数(解决出现e+、e-的问题)** JavaScript在以下情景会⾃动将数值转换为科学计数法:* 1)⼩数点前的数字多于21位。

javascript中数字计算精度缺失问题

javascript中数字计算精度缺失问题

javascript中数字计算精度缺失问题近⼀段时间有个刚刚⼊⾏开发的朋友问我⼀些计数问题,他说,它命名使⽤ toFixed() ⽅法来截取⼩数的长度了,虽然⼤部分都正常,但是有部分会出现结果不准确的问题。

先看图:例如:结果是:但是:下⾯的就不是想要的结果了。

按道理结果应该是 82.1%的,但是实际上却不是这样。

先不说是什么原因导致的。

然后我让他改⼀下:变成:就改变了⼀下运算位置,但是结果⼤不同。

到底哪⼀个才是正确的呢?我们来借助⼀下计算器:结果已经很明显了,正确答案是 82.21%我朋友他的想法是,先将5755 / 7000 然后得出的结果通过 toFixed() ⽅法来截取3位⼩数,然后再乘以 100 来做⼀个百分百。

按道理来说,在平时的计算中这两个写法都是正确的才对啊,但是为什么会出现这样的情况呢?先不要急,我们先来看⼀个最简单的例⼦:看到这⾥的时候你是不是第⼀时间觉得答案是 0.3 ?那看⼀下js打印的结果是怎么样的。

what?0.1 + 0.2 竟然不是等于 0.3 ?没错,这个就是 js 的计算问题了。

所以上⾯出现答案不正确的问题就是因为js的计算⽅式导致的。

要弄清这个问题,⾸先我们需要了解的是:在计算机中数字是如何存储和运算的。

在计算机中,数字⽆论是整点数还是浮点数都是以多位⼆进制的⽅式进⾏存储的。

在JS中数字采⽤的IEEE 754的双精度标准进⾏存储,我们可以⽆需知道他的存储形式,只需要简单的理解成就是存储⼀个数值所使⽤的⼆进制位数⽐较多⽽已,这样得到的数会更加精确。

这⾥为了简单直观,我们使⽤定点数来说明问题。

在定点数中,如果我们以8位⼆进制来存储数字。

对于整数来说,⼗进制的35会被存储为: 00100011 其代表 2^5 + 2^1 + 2^0。

对于纯⼩数来说,⼗进制的0.375会被存储为: 0.011 其代表 1/2^2 + 1/2^3 = 1/4 + 1/8 = 0.375⽽对于像0.1这样的数值⽤⼆进制表⽰你就会发现⽆法整除,最后算下来会是 0.000110011....由于存储空间有限,最后计算机会舍弃后⾯的数值,所以我们最后就只能得到⼀个近似值。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档