Pitfalls about PHP and js floating point operations

javascript

Why is 0.1 + 0.2 not equal to 0.3? (Correct result: 0.30000000000000004)

Why is 0.8 * 7 not equal to 5.6? (Correct result: 5.6000000000000005)

PHP

var_dump (intval (0.58 * 100));

The correct result is 57, not 58

Floating point blame

In fact, these results are not bug language, but the language and principles to achieve relevant, js all digital unified Number, including plastic surgery and all were double-precision (double) type.

And PHP will distinguish between int and float. No matter what language, as long as floating-point operations are involved, there are similar problems, and you must pay attention when using them.

Floating point binary principle

According to the international standard IEEE 754, any of a binary floating-point number can be expressed as V form the following:

V = (-1)s * M * E

    1. (-1)s represents the sign bit. When s=0, V is a positive number; when s=1, V is a negative number.
    2. M represents a significant number, greater than or equal to 1 and less than 2.
    3. 2E means the exponent bit.

 For example: -5.0 decimal, binary is written -101.0 corresponds -1.01 × 22. Then, s=1, M=1.01, E=2.

IEEE 754 stipulates that for a 32-bit floating-point number, the highest 1 bit is the sign bit s, the next 8 bits are the exponent E, and the remaining 23 bits are the significand M.

For a 64-bit floating-point number, the highest 1 bit is the sign bit S, the next 11 bits are the exponent E, and the remaining 52 bits are the significand M.

IEEE 754 also has some special provisions for the significand M and the exponent E.

As mentioned above, 1≤M <2, that is to say, M may be written in the form of 1.xxxxxx, where xxxxxx represents the fractional part. IEEE 754 stipulates that when M is stored in the computer, the first digit of this number is always 1 by default, so it can be discarded, and only the following xxxxxx part is saved. Such as saving 1.01, you can just save 01, until the time to read, then add 1 to the first one. The purpose of this is to save 1 significant figure. Taking a 32-bit floating point number as an example, there are only 23 bits left for M. After rounding off the 1 in the first digit, it is equivalent to saving 24 significant digits.

As for index E, the situation is more complicated.

First, E is an unsigned integer (unsigned int). This means that if E is eight, it is in the range of 0 to 255; if E is 11, which is in the range from 0 to 2047. However, we know that, in the scientific notation E is a negative number, the IEEE 754 specified, the true value of E must minus a number of intermediate E, for an 8-bit E, the middle number is 127; for 11 bit E, the middle number is 1023.
For example, E 10 is 210, so when saved as 32-bit floating point, 10 must be kept to a (true value of E) + 127 = 137 (E) , i.e., 10,001,001.

Then, the exponent E also can be subdivided into three cases:
(1) E 0 is incomplete or not all 1s. In this case, the above rules on the use of floating-point represented, i.e., by subtracting the calculated value of the exponent E 127 (or 1023), to give the true value, then the effective number M is added before the first bit of 1.
(2) E 0's. In this case, floating point exponent E is equal to 1-127 (or 1-1023), the effective number M 1 is no longer coupled with the first one, but the 0.xxxxxx decimal reduction. This is done to represent ± 0, and a small number close to zero.
(3) E are all 1. At this time, if the effective number M are all 0, ± indicates infinity (positive or negative depending on the sign bit s); if not all significant digits M 0, it indicates that the number is not a number (NaN). >

refer to

http://www.laruence.com/2013/03/26/2884.html
http://www.cnblogs.com/qlwy/archive/2012/08/17/2644470.html

 

Reprinted from: http://www.yinqisen.cn/blog-782.html

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326444212&siteId=291194637