Location and solution of the loss of precision of serial number generated by snowflake algorithm

1. Problem background

After the id generated by the snowflake algorithm passes through the browser, all the last few digits of the id become "0000", which makes it impossible to query the details after the list is displayed.

Called by the dubbo service, the normal id is returned, the query log after the gateway also returns the normal id, and the normal id is also returned by the Postmain call, and the list information is checked after clicking the query on the page, and the data id is returned by the Google browser development tool Network The end of has become "0000";

3. The cause of the problem

The value range of Long in Java is -9223372036854775808 to 9223372036854775807 (ie -2^64" to "2^64-1)

The value range of Number in JavaScript is -9007199254740992 to 9007199254740991 (ie -2^53 to 2^53-1)

4. Solutions

Convert Long to String type when passing

Use @JsonSerialize(using = ToStringSerializer.class) annotation when using spring's Json parser

@JsonSerialize(using = ToStringSerializer.class)

private Long id;

5. Extended research

Why the value range of Number in avaScript is -2^53 to 2^53-1?

IEEE 754 specifies four ways to represent floating-point values: single precision (32 bits), double precision (64 bits), extended single precision (more than 43 bits, rarely used) and extended double precision (79 bits above, usually implemented in 80 bits).

The Number type uses the double precision (64-bit) data structure as follows

The 51-62 bits of the Number type are the exponent bits, and the 63 bits are the sign bits, so the value range is -2^53 to 2^53-1

Copy to the relatively official explanation of the Number type.

Perhaps the most interesting data type in ECMAScript is Number. The Number type uses the IEEE 754 format to represent integer and floating-point values ​​(also called double-precision values ​​in some languages). --- Little Red Book

In JavaScript, Number is a numeric data type defined as double-precision 64-bit floating point format (IEEE 754). ---MDN

The Number type uses the IEEE 754 format.

IEEE 754 format

IEEE 754 specifies four ways to represent floating-point values: single precision (32 bits), double precision (64 bits), extended single precision (more than 43 bits, rarely used) and extended double precision (79 bits above, usually implemented in 80 bits).

The Number type uses double precision (64 bits).

This picture explains the structure clearly.

for example

  1. Decimal value: 10.25
  2. Converted to binary => 1010.01
  3. normalized => 1.01001 * 2^3
  4. Storage: 01001 is placed in the mantissa position, and 3 is placed in the exponent position. There are 11 exponent bits, then the frame shift is 1023+3, which is 100...0010, and the frame shift refers to this IEEE754 to represent floating point numbers . The whole expression is like this:

Consider the maximum value that can be expressed, it depends on:

The maximum value that can be represented at a fixed number of digits.

The maximum value of the exponent displacement code is 11 bits 1, and the maximum value of the original code is 10 bits 1 (the highest bit of the original code indicates the sign bit), then the maximum value of y is 1023, and the maximum value of x is 52 bits 1. That is, 1.1111...1 multiplied by 2^1023, that is, 2^1023*(2-2^-52) This value is also the size of Number.MAX_VALUE

maximum safe number

What is the largest safe integer? Refers to the constant Number.MAX_SAFE_INTEGER

Now consider, we look at two numbers 2^53 and 2^53+1.

  • 2^53 We try to represent it in binary: 1 53 0s, normalized 1.0...00 * 2^53
  • What about 2^53+1? We try to represent it in binary: 1 52 0 1 , normalized 1.0...01 * 2^53

Here comes the problem, the mantissa has 53 digits, but only 52 are empty! Its processing method is to ignore the 53rd bit, so the results of these two numbers in the computer are the same!

2**53===2**53+1 //true copy code

Guess you like

Origin blog.csdn.net/u012921921/article/details/130980666