Floating-point arithmetic precision problem
First look at an example:
<?php$a = 0.1; $b = 0.9; $c = 1;var_dump (($a + $b) = = $c); Var_dump (($c-$b) = = $a);? >
$a + $b = = $c return true, correct
$c-$b = = $a return false, error
Why is that?
After the operation, the exact content returned when the precision is 20 bits is as follows:
<?php$a = 0.1; $b = 0.9; $c = 1;printf ("%.20f", $a + $b); 1.00000000000000000000printf ("%.20f", $c-$b); 0.09999999999999997780?>
$c-$b is 0.09999999999999997780, so the comparison with 0.1 returns false
This problem occurs because the floating-point calculation involves precision, which can result in loss of precision when the floating-point number is converted into binary.
Floating point to Binary binary method
The integer part is divided by 2 to take the remainder method
The number of decimal points is multiplied by 2 rounding Method
Example: converting the number 8.5 to binary
the integer part is 8
8/2=4 8%2=0
4/2=2 4%2=0
2/2=1 2%2=0
1:2 Small, so no calculation is required, and the binary of integer 8 is
the fractional part is 0.5
0.5X2 = 1.0
The number of decimal parts after rounding is divided into 0, so no further calculation is required.
Decimal 0.5 binary is 0.1
8.5 binary for 1000.1
computes the binary of the number 0.9
0.9x2=1.8
0.8x2=1.6
0.6x2=1.2
0.2x2=0.4
0.4x2=0.8
0.8x2=1.6
.... After a continuous loop, when the intercept accuracy is n, the number after n is discarded, resulting in loss of precision.
In the previous example, 0.9 was lost in the conversion to binary, resulting in an error when comparing.
so never believe that the float is accurate to the last one, and never compare two floating-point numbers for equality.
A method of correctly comparing floating-point numbers
1. Use the round method to process and then compare
Example:
<?php$a = 0.1; $b = 0.9; $c = 1;var_dump (($c-$b) = = $a); Falsevar_dump (Round ($c-$b), 1) ==round ($a, 1)); True?>
2. Using a high-precision operation method
In the first operation, a high-precision operation is used to ensure that the accuracy is not lost.
the method of high precision operation is as follows:
Bcadd adds two high-precision numbers
Bccomp compares two high-precision numbers, returning -1,0,1
bcp divides two high-precision numbers
Bcmod seeking high precision digital remainder
Bcmul Multiply two high-precision numbers
Bcpow High Precision digital exponentiation
Bcpowmod seeking modulus of high precision digital exponentiation
Bcscale Configure the default number of decimal places, equivalent to "scale=" in Linux BC
bcsqrt to find the square root of high precision number
bcsub to subtract two high-precision numbers
Example:
<?php$a = 0.1; $b = 0.9; $c = 1;var_dump (($c-$b) = = $a); Falsevar_dump (Bcsub ($c, $b, 1) = = $a); True?>
This article explains about the PHP floating-point comparison method, more relevant content please pay attention to the PHP Chinese web.
Related recommendations:
Explanation of how to export query results to CSV method via MySQL
Performance comparison between PHP Array_push and $arr []= $value
How to use PHP to set a session that tightly controls the expiration time