Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: В различных систуациях сравнение происходит по разному
 
 автор: Fractured#   (02.12.2009 в 12:50)   письмо автору
 
 

<?php

set_time_limit
(0);

$f 0.111;

while( 
intval($f) != $f )
{
    
var_dump(intval($f), $fintval($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?

  Ответить  
 
 автор: Trianon   (02.12.2009 в 13:10)   письмо автору
 
   для: Fractured#   (02.12.2009 в 12:50)
 

а что удивляет-то?

(intval($f)) == $f) != (strval(intval($f)) == strval($f))

0.111 машинным образом всяко точно не представимо.
Ошибка точности представления все равно не даст равенства.

  Ответить  
 
 автор: Fractured#   (02.12.2009 в 13:21)   письмо автору
 
   для: 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 в 17:13)   письмо автору
 
   для: Fractured#   (02.12.2009 в 13:21)
 

И всё-таки, как представляется число типа float внутри? Я так думал, что 1 байт (скорее всего) под порядок числа, остальные несколько байт под мантиссу числа. Что может приводить к таким ситуациям? Число "111" типа float может быть представлено неоднозначно?

  Ответить  
 
 автор: Trianon   (02.12.2009 в 18:24)   письмо автору
 
   для: 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 +($n >= $r);
   if(
$p$n -= $r;
   echo 
"$p.";
   if(isset(
$res[$n]))
      break;
   
$res[]= $n;
}
echo 
$n;
?>

  Ответить  
 
 автор: Fractured#   (02.12.2009 в 19:04)   письмо автору
 
   для: Trianon   (02.12.2009 в 18:24)
 

А в чём фокус-то?

  Ответить  
 
 автор: Trianon   (02.12.2009 в 19:10)   письмо автору
 
   для: Fractured#   (02.12.2009 в 19:04)
 

скрипт печатает представление числа 0.111
Это, само собой, периодическая двоичная дробь с нехилой мантиссой.
А поскольку периодические дроби в машине не представляются, так или иначе число получается чуть чуть меньше.
Вот это чуть чуть меньше при умножении на тысячу и дает разность.
При штатном преобразовании в строку эта разность не видна.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования