столкнулся со скриптом одним присутствует следующий код там function mix($a, $b, $c) { $a -= $b; $a -= $c; $a ^= (zeroFill($c, 13)); return $a; } так вот на php 5.2.1 он работает неправильно (как и регулярки) вот эта строка $a ^= (zeroFill($c, 13)); интересует что это тут за операнд такой "^" именно он и глючит и как этот недуг вылечить ? с пхп 3 года в ладах .. а с этим первый раз столкнулся :/ может кто подскажет .. ато поисковики этот символ игнорируют при поиске
это логический оператор xor. и в чем заключается "неправильная" работа? PS. про регулярки тоже хотелось бы услышать.
для примера <? $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 не траблы
если тебе ножно производить операции (особенно побитовые) над столь большими числами, то лучше использовать более предназначенные для этого библиотеки. BCMath, например.
sergwm Ну а ты сам проверь где именно ошибка. XOR работает как полусумматор,т.е. не осуществляет перенос битов при сложении. Например,при PHP: <?php $a = 3; // 11 binary $a ^= 15; // 1111 binary echo $a; ?> ответ должен быть 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 Какого хрена спрашивается?
Amian А кто тебе сказал, что -3 = 1|0011? По твоей логике, -3+1+1+1 будет равно -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
Горбунов Олег И в чем же я не прав? Нормальное отображение -3 это 1|0011 ,а дальше можно переводить в любой другой код,хоть в дополнительный,хоть в обрантый, хоть в ABCD
Обьясните мне каким образом -3 ^= 15 => -14 ? -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)
Amian Я говорю о том, что большинство арифметических операций, тем более двоичные, производятся над внутренним представлением числа, а не над "отображаемым". Внутреннее представление -3 = 1...1101, по крайней мере для машин линейки 8x86, и ничего с этим не поделать. P.S. можно на ты
Автору темы: http://bugs.php.net/39443 Та же самая проблема - ответили, что проблема в слишком больших числах. А при использовании двоичных операторов с вещественными числами результат в общем случае не определен. От себя добавлю, что спорить с ними, и надеяться что они это пофиксят, практически бесполезно достаточно посмотреть, сколько багов они сейчас прикрывают, даже особо не читая их.
А, в х86 значит отрицательные числа хранятся в дополнительном коде, а так вообще существует несколько методов для операций с ними, xотя конечный результат будет 1 и тот же ok
Кстати, в дигитальных системах все данные представляются в двоичном коде и процессор оперирует ими лишь с помощью 2х операций -> сложение с помощью сумматора + умножение/деление с помощью сдвигового регистра.Остальные арифметические операции получаются с помощью извращений с этими 2мя действиями.
все всем спосибо ... разобрался смотрите в 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 */ ?>
LOL мде.. Автору темы, вы каким местом вообще думаете? Конечно не будет работать, потому что в PHP int - 4 байта. это 2 в 32-й степени. Темболее что int signed. Большие числа можно получить на 64 битных системах, где PHP скомпилирован в 64 битной среде, тогда можно будет работать с числами в 8 байт. Ужос на... Помоему перед регистрацией пользователей надо тестировать на знание основ компъюторных наук... Не зря на кафедрах IT наук приподают основы в обязательном порядке.
Точнее от "-2147483648" до "2147483647" Вот примерчик из той же серии PHP: <?php echo intval(3000000000); // "-1294967296" ?> Тогда на форуме будет тусоваться 5-10 человек...
Это и есть 2^31 + 1 разряд знаковый Если число "unsigned" ,то в регистр можно запихнуть и 2^32,не преобразовывая числa в флоаты.Это в 32битный системах ofc.