Ponieważ nie tylko matematyka pływaka jest wadliwa, czasami jest reprezentowana jako is flawed too - i tak jest w tym przypadku.
rzeczywistości nie dostać 0,1, 0,2, ... - i to dość łatwe do sprawdzenia:
$start = 0;
$stop = 1;
$step = ($stop - $start)/10;
$i = $start + $step;
while ($i < $stop) {
print(number_format($i, 32) . "<br />");
$i += $step;
}
Jedyna różnica tutaj, jak widać, jest to, że echo
zastąpione number_format
rozmowy. Ale wyniki są drastycznie różne:
0.10000000000000000555111512312578
0.20000000000000001110223024625157
0.30000000000000004440892098500626
0.40000000000000002220446049250313
0.50000000000000000000000000000000
0.59999999999999997779553950749687
0.69999999999999995559107901499374
0.79999999999999993338661852249061
0.89999999999999991118215802998748
0.99999999999999988897769753748435
Zobacz? Tylko raz to było 0.5
w rzeczywistości - ponieważ ta liczba może być przechowywana w pojemniku pływaka. Wszystkie pozostałe były tylko przybliżeniami.
Jak rozwiązać ten problem? Cóż, jednym radykalnym podejściem jest używanie nie pływaków, ale liczb całkowitych w podobnych sytuacjach. Łatwo zauważyć, że zrobiliście to w ten sposób ...
$start = 0;
$stop = 10;
$step = (int)(($stop - $start)/10);
$i = $start + $step;
while ($i < $stop) {
print(number_format($i, 32) . "<br />");
$i += $step;
}
... to działa ok:
Alternatywnie, można użyć number_format
przekonwertować pływaka do jakiegoś napisu, a następnie porównać to string z preformatowanym floatem. W ten sposób:
$start = 0;
$stop = 1;
$step = ($stop - $start)/10;
$i = $start + $step;
while (number_format($i, 1) !== number_format($stop, 1)) {
print(number_format($i, 32) . "\n");
$i += $step;
}
zaskakująco, kiedy dzielimy przedział na 20: $ kroku = ($ przystanek - start $)/20; jest również ok. – user4035
Prawdopodobnie zaokrąglony błąd zmiennoprzecinkowy. – Blazemonger
Związane z http://stackoverflow.com/questions/3726721/php-math-precision – j08691