In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/03 Report--
See the following questions on Zhihu:
The past life and present life of the problem of floating point accuracy?
1. What is the cause of the problem?
two。 Why other programming languages, such as java, may not be as obvious as js
3. Have you stepped over the pit of floating-point precision in the project?
4. Finally, what solutions are adopted to avoid this problem?
5. Why did you adopt the reform plan?
For example, in chrome js console:
Alert (0.7-0.1); / / output 0.7999999999999999
I was not satisfied with my answer before (I was satisfied with Chen Jiadong's answer). I would like to make a profound and simple summary of this question.
Then read these long articles "[JS Foundation] four problems of operational accuracy loss of JS floating-point numbers (3)", "Summary of the loss of JavaScript Digital accuracy", "detailed description of the Seven data types of JavaScript", and sorted out as follows:
This problem does not occur only in Javascript, any programming language that uses binary floating point numbers will have this problem, but in languages such as C++/C#/Java, methods have been encapsulated to avoid the problem of precision, while JavaScript is a weakly typed language, from the design idea does not have a strict data type for floating point numbers, so the problem of precision error is particularly prominent.
The cause of floating point number loss
Number is the only number type in JavaScript, and the Number type uses "double-precision floating-point numbers" in the IEEE754 standard to represent a number without distinguishing between integers and floating-point numbers (js bit operations may be used to raise the B grid).
Almost all programming languages floating-point numbers use the IEEE floating-point arithmetic standard. Java float 32 floating point number: 1bit sign 8bit index part of 23bit Mantissa. It is recommended to read "the range and accuracy of JAVA floating point numbers"
What is the IEEE-745 floating point representation
IEEE-745 floating-point representation is a binary representation that can accurately represent fractions, such as 1Accord, 2meme, 8and1024.
How is the decimal decimal expressed as converting to binary decimal integers to binary
It is common to convert decimal integers into binary ones: 1 = > 1 2 = > 10 3 = > 101 4 = > 100 5 = > 101 6 = > 110
Six, two, three... 0
3, 2, 3, 3, 3, 3, 3, 3, 2, 3, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 3, 2, 3, 3, 2, 3, 2, 3, 3, 2, 3, 2, 3, 2, 3, 2, 2, 1, 2, 3, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 3, 3, 3, 3, 2, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 2, one
One, two, two, six, two, six, two, two, one
It's 110 upside down.
Decimal to binary
0.25 binary
The rounding of 0.25 to 20.5 is 0
0.5 / 2 / 1.0 rounding is 1.
That is, the binary of 0.25 is 0.01 (the highest bit for the first time and the lowest bit for the last time).
0.8125 binary
0.8125 # 2 # 1.625 rounding is 1
0.625 "2" 1.25 rounding is 1
The rounding of 0.25 to 20.5 is 0
0.5 / 2 / 1.0 rounding is 1.
That is, the binary of 0.8125 is 0.1101 (the highest bit for the first time and the lowest bit for the last time).
Binary of 0.1
0.1 "2" 0.2 = take out the integer part 0
0.2 "2" 0.4 = take out the integer part 0
0.4 "2" 0.8 = take out the integer part 0
0.8 "2" 1.6 = take out the integer part 1
0.6-2-1.2 = take out the integer part 1
0.2 "2" 0.4 = take out the integer part 0
0.4 "2" 0.8 = take out the integer part 0
0.8 "2" 1.6 = take out the integer part 1
0.6-2-1.2 = take out the integer part 1
Then there will be an infinite loop.
0.2 "2" 0.4 = take out the integer part 0
0.4 "2" 0.8 = take out the integer part 0
0.8 "2" 1.6 = take out the integer part 1
0.6-2-1.2 = take out the integer part 1
So the conversion from 0.1 to binary is: 0.0001 1001 1001 1001... (infinite loop)
0.0001 1001 1001 1001... (infinite loop)
Similarly, the binary of 0.2 is 0.0011 0011 0011 0011. (infinite loop)
Storage structure of IEEE-745 floating-point representation
In IEEE754, double-precision floating-point numbers are stored in 64-bit storage, where 8 bytes represent a floating-point number. The storage structure is shown in the following figure:
Exponential bits can be converted to the index values used in the following ways:
Recording numerical range by IEEE-745 floating-point representation
As can be seen from the storage structure, the length of the exponential part is 11 binary, that is, the maximum value that the exponential part can represent is 2047 (2 ^ 11-1).
Take the middle value for offset, which is used to represent the negative index, that is to say, the range of the index is [- 1023 million 1024].
Therefore, this storage structure can represent a range of values ranging from 2 ^ 1024 to 2 ^-1023, and numbers beyond this range cannot be expressed. The conversion of 2 ^ 1024 and 2 ^-1023 to scientific counting is as follows:
1.7976931348623157 × 10 ^ 308
5 × 10 ^-324
Therefore, the maximum value that can be expressed in JavaScript is 1.7976931348623157 × 10308, and the minimum value is 5 × 10-324. The same is true of the java double-precision type double.
These two boundary values can be obtained by accessing the MAX_VALUE property and the MIN_VALUE property of the Number object, respectively:
Number.MAX_VALUE; / / 1.7976931348623157etelephone 308Number.Minority value; / / 5e-324
If the number exceeds the maximum or minimum value, JavaScript returns an incorrect value, which is called a positive overflow (overflow) or a negative overflow (underflow).
Number.MAX_VALUE+1 = = Number.MAX_VALUE; / / trueNumber.MAX_VALUE+1e292; / / InfinityNumber.MIN_VALUE + 1; / 1Number.MIN_VALUE-3eMur324; / / 0Number.MIN_VALUE-2eMur324; / / 5e-324IEEE-745 floating-point representation numerical accuracy
In the 64-bit binary system, the symbol bit determines the positive or negative of a number, the exponential part determines the size of the value, and the decimal part determines the accuracy of the value.
According to IEEE754, the first significant digit is always 1 by default. Therefore, before the number of bits that represent precision, there is also a "hidden bit", fixed at 1, but it is not saved in 64-bit floating-point numbers. That is, significant numbers are always in the form of 1.xx...xx, where the portion of the xx..xx is stored in 64-bit floating-point numbers, with a maximum length of 52 bits. Therefore, the valid number provided by JavaScript is up to 53 binary digits, and its internal actual form is:
(- 1) ^ symbol bit * 1.xx...xx * 2 ^ exponential bit
This means that the range of integers that JavaScript can represent and perform precise arithmetic operations is: [- 2 ^ 53-1, 2 ^ 53-1], that is, from the minimum value-9007199254740991 to the maximum value 9007199254740991.
Math.pow (2,53)-1; / / 9007199254740991-Math.pow (2,53)-1; / /-9007199254740991
You can get the maximum and minimum values through Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER, respectively.
Console.log (Number.MAX_SAFE_INTEGER); / / 9007199254740991console.log (Number.MIN_SAFE_INTEGER); / /-9007199254740991
For integers beyond this range, JavaScript can still operate, but it does not guarantee the accuracy of the results.
Math.pow (2,53); / / 9007199254740992Math.pow (2,53) + 1; / 90071992547409929007199254740999900719925474099290071992547409921; / / 90071992547409999200.9234567890123456786IEEE float 745 loss of numerical accuracy
All the numbers in the computer are stored in binary, and the binary floating point representation can not accurately represent a simple number like 0.1.
If you want to calculate the result of 0.1 + 0.2, the computer will first convert 0.1 and 0.2 into binary, then add them together, and finally convert the added result to decimal.
However, there are some floating-point numbers that have an infinite loop when converted to binary. For example, if decimal 0.1 is converted to binary, you will get the following result:
0.0001 1001 1001 1001... (infinite loop)
0.0011 0011 0011 0011... (infinite loop)
The Mantissa part of the storage structure can only represent up to 53 bits. In order to represent 0.1, it can only be rounded to imitate the decimal system, but the binary system has only 0 and 1, so it becomes 0 rounding 1. Therefore, the binary representation of 0.1 in the computer is as follows:
0.0001 1001 1001 1001
0.0011 0011 0011 0011
It is represented by standard counting as follows:
− 1) 0 × 2 ^ 4 × (1.1001100110011001100110011001100110011001100110011010) 2
− 1) 0 × 2 ^ 3 × (1.1001100110011001100110011001100110011001100110011010) 2
When calculating the addition of floating-point numbers, you need to "align" first, turn a smaller index into a larger index, and move the decimal part to the right accordingly:
Finally, the calculation process of "0.1 + 0.2" in the computer is as follows:
After the above calculation process, the result of 0.1 + 0.2 can also be expressed as:
(− 1) 0 × 2 − 2 × (1.0011001100110011001100110011001100110011001100110011001100110100) 2 = > .0.300000000000004
Convert this binary result to a decimal representation through JS:
(- 1) * * 0 * 2 (0b10011001100110011001100110011001100110011001100110100 * 2); / / 0.300000000000004
Console.log (0.1 + 0.2); / / 0.300000000000004
This is a typical case of precision loss. As can be seen from the above calculation process, there is a precision loss when 0.1 and 0.2 are converted to binary, and there is another precision loss for the calculated binary. Therefore, the results obtained are not accurate.
Solution to floating-point data loss
The scores we often use (especially in financial calculation) are decimal scores, 1max, 10pm, 1max, 100, etc. Perhaps later circuit design may support decimal number types to avoid these rounding problems. Before that, you prefer to use large integers for important financial calculations, for example, to use integer 'points' rather than decimal 'yuan' to calculate goods ratio units
That is, before the operation, we upgrade the number participating in the operation (to the power of 10 to the power of X) to an integer, and then downgrade it to the power of 0.1 to the power of X.
There is a BigDecimal library in java and big.js js-big-decimal.js in js. Of course, BCD coding is for the decimal high-precision computing system.
BCD coding
BCD code (usually in the form of 8421BCD code) is also called binary code decimal number or binary-decimal code. Use 4-digit binary numbers to represent the 10 numbers 0,9 in 1-digit decimal number. It is generally used for high precision calculation. For example, accounting systems often require accurate calculations of long strings of numbers. Compared with the general floating-point counting method, the use of BCD code can not only preserve the accuracy of the numerical value, but also save the time spent on the computer for floating-point operation.
Why use binary system?
Binary system is easier to implement physically in circuit design, because most electronic devices have two stable states, such as the turn-on and cut-off of transistors, high and low voltage, magnetic and non-magnetic. It is difficult to find an electronic device with ten stable states.
The binary rule is simple. There are 55 rules for summation and quadrature in decimal system, and only 3 in binary system, which can simplify the design of physical devices such as arithmetic unit. In addition, the state of computer components is less, which can enhance the stability of the whole system.
It is consistent with the logical quantity. Binary numbers 0 and 1 correspond to logical quantities "true" and "false", so it is natural to use binary numbers to represent binary logic.
High reliability. Only two numbers 0 and 1 are used in the binary system, so it is not easy to make errors in transmission and processing, so the computer can be guaranteed to have high reliability.
I think it's mainly because of the first one. If, for example, decimal components can be designed, then it is no longer necessary to design their calculators.
Some typical problems in the loss of Digital accuracy in JS
The addition of two simple floating point numbers
0 1 + 0 2! = 0 3 / / true
ToFixed does not round (Chrome)
1.335.toFixed 2 / / 1.33
One more question: how many decimal places is the highest precision of floating point numbers in js numeric types? (16 or 17?. Why?
The range of integers that JavaScript can represent and perform precise arithmetic operations is: [- 2 ^ 53-1, 2 ^ 53-1], that is, from the minimum value-9007199254740991 to the maximum value 9007199254740991. 9007199254740991'.length//16
According to IEEE754, the first significant digit is always 1 by default. Therefore, before the number of bits that represent precision, there is also a "hidden bit", fixed at 1, but it is not saved in 64-bit floating-point numbers. That is, significant numbers are always in the form of 1.xx...xx, where the portion of the xx..xx is stored in 64-bit floating-point numbers, with a maximum length of 52 bits. Therefore, the valid number provided by JavaScript is up to 53 binary digits
Let axiom 1amp 3
A.toString (); / / "0.3333333333333333"
A.toString (); .length//18
A total of 0.3333333333333333333 334 331 of the total number of three years.
0.3333333333333332.
Related links:
Http://0.30000000000000004.com
Http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Floating point accuracy analysis: inaccurate decimal calculation + floating point accuracy loss source-computer science-Zhou Jun's personal website, if there is anything wrong, please leave a message at my origin server. Not an update.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.