问题: [雪花(snowflake)算法]生成的id如果用long类型返回前端(例如4858024458742925186),精度会丢失。
Number精度是16位,超过会造成精度丢失。
目前解决方法是后端转成字符串返回处理。 并注意前端不要转换数字类型。 例如 +(Number)
等。
说明
响应体中的长整型显示错误 · Issue #135 · xiaoymin/swagger-bootstrap-ui
JavaScript 内部只有一种数字类型 Number,所有数字都是采用 IEEE 754 标准定义的双精度 64 位格式存储,即使整数也是如此。这就是说,JavaScript 语言的底层根本没有整数,所有数字都是小数(64 位浮点数)。其结构如图:
各位的含义如下:
- 1 位(s) 用来表示符号位,0 表示正数,1 表示负数
- 11 位(e) 用来表示指数部分
- 52 位(f) 表示小数部分(即有效数字)
双精度浮点数(double
)并不是能够精确表示范围内的所有数, 虽然双精度浮点型的范围看上去很大: 。 可以表示的最大整数可以很大,但能够精确表示,使用算数运算的并没有这么大。因为小数部分最大是 52
位,因此 JavaScript 中能精准表示的最大整数是 ,十进制即 9007199254740991
。
js
console.log(Math.pow(2, 53) - 1);
console.log(1L<<53);
9007199254740991
console.log(Math.pow(2, 53) - 1);
console.log(1L<<53);
9007199254740991
JavaScript 有所谓的最大和最小安全值:
js
console.log(Number.MAX_SAFE_INTEGER);
console.log(Number.MIN_SAFE_INTEGER);
9007199254740991 - 9007199254740991;
console.log(Number.MAX_SAFE_INTEGER);
console.log(Number.MIN_SAFE_INTEGER);
9007199254740991 - 9007199254740991;
josdejong/lossless-json: Parse JSON without risk of losing numeric information
js
import { parse, stringify, isSafeNumber, isInteger } from 'lossless-json';
const str = '{"id":1234567890123456789,"id2":12345, "name":"收到"}';
// 精度丢失
const x = JSON.parse(str).id;
console.log('content:', x); // 1234567890123456800
const json = parse(str); // {foo: 'bar'}
// 精度没有丢失
console.log('json:', json);
/*
json: {id: e}
id: e {isLosslessNumber: true, value: '1234567890123456789'}
[[Prototype]]: Object
*/// 测试解析common
const xxxxx = parse(str, undefined, (value) => {
console.log('isSafeNumber', value, isSafeNumber(value));
if (isSafeNumber(value)) {
return +value;
}
return value.toString();
});
console.log(xxxxx);
import { parse, stringify, isSafeNumber, isInteger } from 'lossless-json';
const str = '{"id":1234567890123456789,"id2":12345, "name":"收到"}';
// 精度丢失
const x = JSON.parse(str).id;
console.log('content:', x); // 1234567890123456800
const json = parse(str); // {foo: 'bar'}
// 精度没有丢失
console.log('json:', json);
/*
json: {id: e}
id: e {isLosslessNumber: true, value: '1234567890123456789'}
[[Prototype]]: Object
*/// 测试解析common
const xxxxx = parse(str, undefined, (value) => {
console.log('isSafeNumber', value, isSafeNumber(value));
if (isSafeNumber(value)) {
return +value;
}
return value.toString();
});
console.log(xxxxx);