1、IEEE 754 双精确度浮点数(Double 64 Bits)中尾数部分是用来存储整数的有效位数,为 52 位,加上省略的一位 1 可以保存的实际数值为
Math.pow(2, 53) // 9007199254740992
Number.MAX_SAFE_INTEGER // 最大安全整数 9007199254740991
Number.MIN_SAFE_INTEGER // 最小安全整数 -9007199254740991
2、实际存储时 如果超过 最值,会发生转化
const num = 200000436035958034;
console.log(num); // 200000436035958050
还有常见的场景是 经过JSON.parse 序列化后 大数超过最值, 也会被转化; 原因是 JSON 的schema 是 object, array, number, or string , 所以对数字自动转化
3、处理方式
- 转为字符串: 最为常见
- BigInt
// 方法1
200000436035958034n; // 200000436035958034n
// 方法2
BigInt('200000436035958034') // 200000436035958034n
// 注意要使用字符串否则还是会被转义
BigInt(200000436035958034) // 200000436035958048n 这不是一个正确的结果
但BigInt 类型 不能直接进行JOSN.parse , 会报错,因为不符合JSON的schema
- 第三方库: json-bigint
不要直接使用 JSON.parse() ,在接收数据流之后,先通过字符串方式进行解析,利用 json-bigint 这个库,会自动的将超过 2 的 53 次方类型的数值转为一个 BigInt 类型,再设置一个参数 storeAsString: true 会将 BigInt 自动转为字符串。
node端使用:
const http = require('http');
const JSONbig = require('json-bigint')({ 'storeAsString': true});
http.createServer((req, res) => {
if (req.method === 'POST') {
let data = '';
req.on('data', chunk => {
data += chunk;
});
req.on('end', () => {
try {
// 使用第三方库进行 JSON 序列化
const obj = JSONbig.parse(data)
console.log('经过 JSON 反序列化之后:', obj);
res.setHeader("Content-Type", "application/json");
res.end(data);
} catch(e) {
console.error(e);
res.statusCode = 400;
res.end("Invalid JSON");
}
});
} else {
res.end('OK');
}
}).listen(3000)
axios中使用:
const axios = require('axios').default;
const JSONbig = require('json-bigint')({ 'storeAsString': true});
const request = axios.create({
baseURL: 'http://localhost:3000',
transformResponse: [function (data) {
return JSONbig.parse(data)
}],
});
request({
url: '/api/test'
}).then(response => {
// 200000436035958034
console.log(response.data.num);
});
总结自Node.js 中遇到大数处理精度丢失如何解决?前端也适用!
hi~ 今天的你开心不~~
网友评论