За последние 24 часа нас посетили 50925 программистов и 1740 роботов. Сейчас ищут 888 программистов ...

операнд ^ и php 5.2.1 .. как боротся

Тема в разделе "Прочие вопросы по PHP", создана пользователем sergwm, 12 апр 2007.

  1. sergwm

    sergwm Активный пользователь

    С нами с:
    12 апр 2007
    Сообщения:
    3
    Симпатии:
    0
    столкнулся со скриптом одним присутствует следующий код там

    function mix($a, $b, $c)
    {
    $a -= $b;
    $a -= $c;
    $a ^= (zeroFill($c, 13));

    return $a;
    }

    так вот на php 5.2.1 он работает неправильно (как и регулярки)

    вот эта строка $a ^= (zeroFill($c, 13)); интересует что это тут за операнд такой "^"
    именно он и глючит
    и как этот недуг вылечить ?

    с пхп 3 года в ладах .. а с этим первый раз столкнулся :/

    может кто подскажет ..

    ато поисковики этот символ игнорируют при поиске
     
  2. simpson

    simpson Активный пользователь

    С нами с:
    11 фев 2006
    Сообщения:
    1.650
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    это логический оператор xor.

    и в чем заключается "неправильная" работа?

    PS. про регулярки тоже хотелось бы услышать.
     
  3. sergwm

    sergwm Активный пользователь

    С нами с:
    12 апр 2007
    Сообщения:
    3
    Симпатии:
    0
    для примера

    <?
    $a = 4523419682;
    $a = $a - 4608221683;
    $a = $a - 4653896912;
    $a ^= 43814;
    ?>

    на 5.0.3 выдает -443704711

    на 5.2.1 выдает -21474398348

    вот такие нехорошие результаты ...


    с регулярками были тоже проблемы на этой версии ..
    точно в чем трабл сказать не могу но факт что preg_match неправильно обробатывал ..
    сверял с работой на 4.x и 5.x только на 5.2.1 не траблы
     
  4. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    если тебе ножно производить операции (особенно побитовые) над столь большими числами, то лучше использовать более предназначенные для этого библиотеки. BCMath, например.
     
  5. Amian

    Amian Активный пользователь

    С нами с:
    15 мар 2007
    Сообщения:
    189
    Симпатии:
    0
    sergwm
    Ну а ты сам проверь где именно ошибка. XOR работает как полусумматор,т.е. не осуществляет перенос битов при сложении.
    Например,при
    PHP:
    1.  
    2. <?php
    3. $a = 3;    // 11 binary
    4. $a ^= 15; // 1111 binary
    5.  
    6. echo $a;
    7. ?>
    8.  
    ответ должен быть 12 т.к.
    0011 bin
    1111 bin
    -----
    1100 bin -> 12 decemal

    Если выдаёт такой же результат и в 5.21,то ошибка не в правильности работы елемента XOR,а в его работе при переполнении 32-битного регистра.А когда регистр переполняется ,то числа отображаются уже как флоаты и результат будет разным.

    Кстати,PHP неправильно обрабатывает XOR если 1 из чисел с отрицательным знаком.Например -3 ^= 15 он выдаёт -14 т.е.
    1|0011
    0|1111
    -----
    1|1110 -> -14 decemal

    Какого хрена спрашивается?
     
  6. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Amian
    А кто тебе сказал, что -3 = 1|0011?
    По твоей логике, -3+1+1+1 будет равно -0 (ноль со знаком) :D
    Отрицательные числа всегда представлялись как двоичное дополнение положительного плюс единица, чтобы правильно работали операции сложения/вычитания.
     
  7. Amian

    Amian Активный пользователь

    С нами с:
    15 мар 2007
    Сообщения:
    189
    Симпатии:
    0
    Dagdamor
    -3 будет 1|0011 и действительно,будет -0 если -3+1+1+1 :) Вы видимо немного путаете понятия,перед сложением отрицательные числа переводятся в обратный код и -3 будет выглядеть как 1|1100 , а после сложения результат переводится уже назад , т.е. 1-3 = -2 -> (1|0011 переводим в обрантый код -> 1|1100+0|0001=1|1101 переводим назад в обычный -> 1|0010 -> -2 decemal :) А прибавление еденицы назад делается при смене знака когда происходит переполнение.
    Например:
    7-3=4 => 0|00111+1|00011 переводим в обратный код => 0|00111+1|11100=10|00011=0|00011+1=0|00100 => 4 decemal ;)
     
  8. Anonymous

    Anonymous Guest

    +1 Учите основы.
     
  9. Amian

    Amian Активный пользователь

    С нами с:
    15 мар 2007
    Сообщения:
    189
    Симпатии:
    0
    Горбунов Олег
    И в чем же я не прав? Нормальное отображение -3 это 1|0011 ,а дальше можно переводить в любой другой код,хоть в дополнительный,хоть в обрантый, хоть в ABCD :p
     
  10. Amian

    Amian Активный пользователь

    С нами с:
    15 мар 2007
    Сообщения:
    189
    Симпатии:
    0
    Обьясните мне каким образом -3 ^= 15 => -14 ? :p

    -3 dec = 1|0011 => 1|1100
    15 dec = 0|1111 => 0|1111

    1|1100 XOR 0|1111=1|0011=1|1100=-12 decemal ,и где же тут -14?

    Кстати,вот формула XOR на логическом уровне: A XOR B = NOT (A AND B) AND (A OR B)
     
  11. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Amian
    Я говорю о том, что большинство арифметических операций, тем более двоичные, производятся над внутренним представлением числа, а не над "отображаемым". Внутреннее представление -3 = 1...1101, по крайней мере для машин линейки 8x86, и ничего с этим не поделать.
    P.S. можно на ты :)
     
  12. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    Автору темы:
    http://bugs.php.net/39443
    Та же самая проблема - ответили, что проблема в слишком больших числах. А при использовании двоичных операторов с вещественными числами результат в общем случае не определен. От себя добавлю, что спорить с ними, и надеяться что они это пофиксят, практически бесполезно ;) достаточно посмотреть, сколько багов они сейчас прикрывают, даже особо не читая их.
     
  13. Amian

    Amian Активный пользователь

    С нами с:
    15 мар 2007
    Сообщения:
    189
    Симпатии:
    0
    А, в х86 значит отрицательные числа хранятся в дополнительном коде, а так вообще существует несколько методов для операций с ними, xотя конечный результат будет 1 и тот же :p

    ok :)
     
  14. Amian

    Amian Активный пользователь

    С нами с:
    15 мар 2007
    Сообщения:
    189
    Симпатии:
    0
    Кстати, в дигитальных системах все данные представляются в двоичном коде и процессор оперирует ими лишь с помощью 2х операций -> сложение с помощью сумматора + умножение/деление с помощью сдвигового регистра.Остальные арифметические операции получаются с помощью извращений с этими 2мя действиями.
     
  15. sergwm

    sergwm Активный пользователь

    С нами с:
    12 апр 2007
    Сообщения:
    3
    Симпатии:
    0
    все всем спосибо ... разобрался

    смотрите в bugs.php.net
    там этот баг описан

    вот собстно окончательный код по которому все видно
    <?
    $a = -4738698913;
    $b = 43814;
    echo decbin($a) . "\n";
    echo "xor\n";
    printf("1%0" . (strlen(decbin($a)) - strlen(decbin($b)) - 1) . "s", "");
    echo decbin($b) . "\n";
    echo "=\n";
    echo decbin($a ^ $b) . "\n";

    /*
    PHP 5.0.3 - Normal result
    11100101100011010011000101011111
    xor
    10000000000000001010101100100110
    =
    11100101100011011001101001111001

    PHP 5.2.1 - Bad result
    10000000000000000000000000000000
    xor
    10000000000000001010101100100110
    =
    10000000000000001010101100100110
    */
    ?>
     
  16. Amian

    Amian Активный пользователь

    С нами с:
    15 мар 2007
    Сообщения:
    189
    Симпатии:
    0
    Тут в обоих случаях нормальный результат,используй числа больше 2^32 чтобы появился этот баг.
     
  17. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    LOL

    мде..

    Автору темы, вы каким местом вообще думаете? Конечно не будет работать, потому что в PHP int - 4 байта. это 2 в 32-й степени. Темболее что int signed. Большие числа можно получить на 64 битных системах, где PHP скомпилирован в 64 битной среде, тогда можно будет работать с числами в 8 байт.

    Ужос на... Помоему перед регистрацией пользователей надо тестировать на знание основ компъюторных наук... Не зря на кафедрах IT наук приподают основы в обязательном порядке.
     
  18. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Точнее от "-2147483648" до "2147483647"

    Вот примерчик из той же серии
    PHP:
    1. <?php
    2. echo intval(3000000000); // "-1294967296"
    3. ?>
    Тогда на форуме будет тусоваться 5-10 человек...
     
  19. Amian

    Amian Активный пользователь

    С нами с:
    15 мар 2007
    Сообщения:
    189
    Симпатии:
    0
    Это и есть 2^31 + 1 разряд знаковый :p Если число "unsigned" ,то в регистр можно запихнуть и 2^32,не преобразовывая числa в флоаты.Это в 32битный системах ofc.
     
  20. Vladson

    Vladson Старожил

    С нами с:
    4 фев 2006
    Сообщения:
    4.040
    Симпатии:
    26
    Адрес:
    Estonia, Tallinn
    Ты так говоришь как будто я этого не знаю :)
     
  21. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    В PHP unsigned нету, так что его можно не вспоминать даже :)