起因
近期在项目中有出现后端返回大数值,一使用就会被js改写值,因为它超出了js的最大安全数。
可以看到这个数值大于 Number.MAX_SAFE_INTEGER 就不被保证正确了。
需求
- 通过 AJAX 获取后端返回的值正确显示;
- 通过换算得到正确结果;
正确显示返回值
后端返回数据类型为数字并且数值大于安全值会导致值显示错误,需后端返回字符串类型即可解决取值错误问题。
通过换算得到正确结果
思路
-
有的同学肯定会说直接相加不就行了吗?答案肯定是不行的,转为数字就会因为超出安全范围而得到错误的结果。
-
所以我想到用循环字符串使其个位相加、百位相加、千位...以此类推。
-
每一个商品的单价长度会不一致,如果直接进行循环相加会导致个位、十位不能正常对齐,所以在求和前我们需要对所有数值进行补0操作,已确保他们的位数一致。
-
最后我们就可以进行循环求和进位换算了。
const res = [{
"name": "房子",
"price": "9999999999999999"
}, {
"name": "装修",
"price": "108"
}]
// 得出最长位数用于补0和循环求和
let maxLen = res.reduce((prev, current) => {
if (!prev || prev < current.price.length) prev = current.price.length
return prev
}, 0),
// 总和
total = '',
// 储存余数用于进位
remaining = 0
// 计算结果前先进行补位
res.forEach(item => {
if (item.price.length < maxLen) {
[...new Array(maxLen - item.price.length).keys()].forEach(() => {
item.price = '0' + item.price
})
}
})
// 计算得出结果
for (let i = maxLen - 1; i > -1; i--) {
// 每一位相加得出的结果
const n = res.reduce((prev, current) => prev + Number(current.price[i]), remaining),
// 个位数值
bits = n % 10
// 余数进位
remaining = (n - bits) / 10;
// 个位数值
total = bits.toString() + total
}
// 如果进位值大于 0
if (remaining) total = remaining.toString() + total
思路
- 采用内置对象 BigInt 进行换算
const res = [{ "name": "房子", "price": "9999999999999999"}, { "name": "装修", "price": "19878763"}]
// 使用BigInt
res.reduce((prev, current) => {
return BigInt(current.price) + prev
}, BigInt(0)).toString()