JavaScript Number范围及超出范围运算方法

您所在的位置:网站首页 超出扫码规定范围怎么处理 JavaScript Number范围及超出范围运算方法

JavaScript Number范围及超出范围运算方法

2024-05-27 07:15| 来源: 网络整理| 查看: 265

今天在LeetCode上练刀法的时候,遇到了一个问题,两数相加,发现有个边界条件就是输入超过number的范围(大数操作),这就涉及到了知识的盲区,看来刀法还是不锋利,这里总结一下number的问题。

原题目如下: 给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。 示例: 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807

1 JavaScript中Number的范围 1.1 Number范围1.2 Number在内存中的实现1.3 Number实现对运算带来的问题 1.3.1 Number带来浮点预算精度问题1.3.2 Number带来大数问题 2 解决方案 2.1 使用big-integer处理大数2.2 使用数组处理大数的sample code

1 JavaScript中Number的范围

JavaScript中所有的数字,无论是整数还是小数,其类型均为Number。在程序内部,Number类型的实质是一个64位的浮点数。(8字节)

1.1 Number范围

数字类型采用64位浮点格式表示,我们可以利用Number对象的属性Number.MAX_VALUE , Number.MIN_VALUE来查看; JavaScript中Number范围为正负2的53次方,也即从最小值-9007199254740992到最大值+9007199254740992之间的范围。 −9007199254740992 and 9007199254740992 (即正负2的53次方) 11位

1.2 Number在内存中的实现

JavaScript 里的数字是采用 IEEE 754 标准的 64 位双精度浮点数。该规范定义了浮点数的格式,对于64位的浮点数在内存中的表示,最高的1位是符号位,接着的11位是指数,剩下的52位为有效数字,具体: 这里写图片描述

第0位:符号位, s 表示 ,0表示正数,1表示负数; 第1位到第11位:储存指数部分, e 表示 ; 第12位到第63位:储存小数部分(即有效数字),f 表示, 符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。 IEEE 754规定,有效数字第一位默认总是1,不保存在64位浮点数之中。也就是说,有效数字总是1.xx…xx的形式,其中xx..xx的部分保存在64位浮点数之中,最长可能为52位。因此,JavaScript提供的有效数字最长为53个二进制位(64位浮点的后52位+有效数字第一位的1)。

1.3 Number实现对运算带来的问题

http://www.css88.com/archives/7340

1.3.1 Number带来浮点预算精度问题 const float1 =7.9; const float2 = 0.8; console.log(float1-float2); //7.1000000000000005

这种问题发生的原因: 首先,十进制的7.9和0.8都会被转换成二进制,但由于浮点数用二进制表达时是无穷的。标准的 64 位双精度浮点数的小数部分最多支持 53 位二进制位,所以浮点数小数位的限制而截断的二进制数字,进行运算后,再转换为十进制,就会产生误差。 这种问题根本原因是在于:计算机都是0或1标识,对于某浮点准确值,是通过不断增加位数去逼近该值。浮点数实现这种方式就是移位运算,所以不管是在表示还是运算时,都会出现误差

如何解决: 1 简单的方法使用toFixed parseFloat((数学表达式).toFixed(digits)); // toFixed() 精度参数须在 0 与20 之间 // 运行 console.log(parseFloat((float1-float2).toFixed(10)));//7.1 toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。参数为指定小数位数 2 将小数部分单独提取出来作为整数运算然后在拼接,这里我们可以使用封装好的lib。

1.3.2 Number带来大数问题

当我们要计算的值超过了Number最大整数范围时,就会直接报错。 所以如果要进行这样的运算要进行特殊的处理。我自己实现的方式是,将大数的每一位存进数组,然后对两个数组的每一个位单独运算。得到运算结果。

2 解决方案 2.1 使用big-integer处理大数

npm install big-integer

const bigInt = require("big-integer"); let largeNumber1 = bigInt("756435643634734534563423785643879569067365464564324235345"); let largeNumber2 = bigInt("75643564366756753687325768753897357378673698098546456235345"); console.log(largeNumber1); console.log(largeNumber2); console.log(bigInt("75643564363473453456342378564387956906736786786546456235345").add("756435643667567536567567873257687538973573786736546456235345"));

返回值为一个object 其中,超过限制的数字被分隔为了数组

{ [Number: 8.32079208031041e+59] value: [ 2470690, 2309291, 3105735, 5495880, 5182207, 239102, 1040990, 7920803, 8320 ], sign: false, isSmall: false }

其中Number为值,value为分割后的数字数组。

2.2 使用数组处理大数的sample code function numToArray(num){//仅用于模拟一个由数字组成的数组测试而已 let NumArray = new Array(); while(num !== 0){ let ret = num%10; num = Math.floor(num/10) NumArray.push(ret); } return NumArray; } function numBitArrayAdd(nums1, nums2){ let i = 0; let length = nums1.length > nums2.length ? nums1.length : nums2.length; let retNums = new Array(); let addBitFlag = 0; let addItem1 = 0; let addItem2 = 0; let ret = 0; for(;(i < length || addBitFlag !== 0); i++){ addItem1 = nums1[i] === undefined ? 0 : nums1[i]; addItem2 = nums2[i] === undefined ? 0 : nums2[i]; ret = addItem1 + addItem2 + addBitFlag; if(ret > 9){ addBitFlag = 1; ret = (ret % 10); } else{ addBitFlag = 0; } retNums[i] =ret; } return retNums; } const float1 =7.9; const float2 = 0.05; console.log(float1-float2); console.log("Number MAX:"+ Number.MAX_VALUE); console.log("Number MIN:"+ Number.MIN_VALUE); let testNum1 = 134892; let testNum2 = 2381; let testArray1 = numToArray(testNum1); let testArray2 = numToArray(testNum2); let resArray = numBitArrayAdd(testArray1, testArray2); console.log(testArray1); console.log(testArray2); console.info(resArray); console.info(resArray.reverse()); console.info(testNum1+testNum2);


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3