|
|
|
|
<?php
set_time_limit(0);
$f = 0.111;
while( intval($f) != $f )
{
var_dump(intval($f), $f, intval($f) == $f); echo '<br />';
$f *= 10;
}
echo $f;
?>
|
Результат:
int(0) float(0.111) bool(false)
int(1) float(1.11) bool(false)
int(11) float(11.1) bool(false)
int(111) float(111) bool(false)
int(1110) float(1110) bool(false)
int(11100) float(11100) bool(false)
int(111000) float(111000) bool(false)
int(1110000) float(1110000) bool(false)
int(11100000) float(11100000) bool(false)
int(111000000) float(111000000) bool(false)
int(1110000000) float(1110000000) bool(false)
int(-1784901888) float(11100000000) bool(false)
int(-669149696) float(111000000000) bool(false)
int(1898437632) float(1.11E+12) bool(false)
int(1804507136) float(1.11E+13) bool(false)
...
|
WTF? | |
|
|
|
|
|
|
|
для: Fractured#
(02.12.2009 в 12:50)
| | а что удивляет-то?
(intval($f)) == $f) != (strval(intval($f)) == strval($f))
0.111 машинным образом всяко точно не представимо.
Ошибка точности представления все равно не даст равенства. | |
|
|
|
|
|
|
|
для: Trianon
(02.12.2009 в 13:10)
| | Почему в различных ситуациях сравнение происходит по-разному?
<?php
$a = (int) 111;
$b = (float) 111;
var_dump($a, $b, $a == $b); # int(111) float(111) bool(true)
?>
|
UPD "В различных систуациях сравнение происходит по-разному" Требую исправлений! | |
|
|
|
|
|
|
|
для: Fractured#
(02.12.2009 в 13:21)
| | И всё-таки, как представляется число типа float внутри? Я так думал, что 1 байт (скорее всего) под порядок числа, остальные несколько байт под мантиссу числа. Что может приводить к таким ситуациям? Число "111" типа float может быть представлено неоднозначно? | |
|
|
|
|
|
|
|
для: Fractured#
(02.12.2009 в 13:21)
| | потому что чистое 0.111 не равно 0.111 в машинной арифметике
а значит 0.111 * 1000 не равно 111
Неоднократно показывал этот фокус здесь:
<?php
$n = '111';
$r = 1;
while(strlen($r) <= strlen($n)) $r *= 10;
$n = intval($n);
$res = array($n);
echo '0.';
for(;;)
{
echo "$n<br>";
$n *= 2;
$p = 0 +($n >= $r);
if($p) $n -= $r;
echo "$p.";
if(isset($res[$n]))
break;
$res[]= $n;
}
echo $n;
?>
|
| |
|
|
|
|
|
|
|
для: Trianon
(02.12.2009 в 18:24)
| | А в чём фокус-то? | |
|
|
|
|
|
|
|
для: Fractured#
(02.12.2009 в 19:04)
| | скрипт печатает представление числа 0.111
Это, само собой, периодическая двоичная дробь с нехилой мантиссой.
А поскольку периодические дроби в машине не представляются, так или иначе число получается чуть чуть меньше.
Вот это чуть чуть меньше при умножении на тысячу и дает разность.
При штатном преобразовании в строку эта разность не видна. | |
|
|
|