Привет всем, я думаю, это может быть баг, но он меня убивает. Я использую MySQL 5.1.41 на сервере Ubuntu Linux. Я пытаюсь написать функцию для создания случайного значения BIGINT со знаком. Поскольку точность RAND () слишком мала для генерации полного диапазона возможных значений BIGINT, я решил попытаться объединить четыре 32-битных слова с помощью битовых операторов.
Я запустил MySQL Workbench и попробовал следующее, чтобы проверить, правильно ли работают операторы битового сдвига с отрицательными числами:
SELECT HEX((0x1ACE - 0x8000) << 0x10);
0x1ACE - 0x8000 равно -25906, поэтому, если я сдвигаю 16 бит влево, мне нужно умножить на 65536, верно? Ответ, который я получил, был 0xFFFFFFFF9ACE0000, что является подписанным представлением -1697775616 или -25906 * 65536. Wunderbar, это работает !!!
Итак, мой план состоял в том, чтобы использовать это для генерации первого 32-битного слова случайного подписанного BIGINT и использовать простой цикл для добавления еще трех 32-битных слов к значению, сдвигая биты на четыре байта за раз. Я взволнованно начал с того, что поместил следующий код в свою функцию, используя жестко запрограммированное значение для проверки моего плана:
DECLARE x BIGINT;
SET x = (0x1ACE - 0x8000) << 0x10;
Если я устанавливаю значение так, чтобы сдвигаемое значение было положительным, все работает нормально. Однако после выполнения этого вычисления со смещенным отрицательным значением (-25906 в данном случае) я продолжал получать, что x был 0x7FFFFFFFFFFFFFFF, что является максимальным положительным значением 64-битного целого числа со знаком. Я совершенно сбит с толку. Точно такая же операция генерирует совершенно другой результат в зависимости от того, находится ли она в операции SET в функции или в операторе SELECT.
Итак, я начал возиться с тем, подписан ли x или нет, и все стало действительно странно. Я попытался сделать x без знака и попробовал следующее:
DECLARE x BIGINT UNSIGNED;
SET x = (0x1ACE - 0x8000);
Когда я это сделал, я получил x, равный нулю. Неудивительно, поскольку x беззнаковый и результат отрицательный. Однако, ради шутки, я попробовал это:
DECLARE x BIGINT UNSIGNED;
SET x = (0x1ACE - 0x8000) << 0;
К моему удивлению, x был установлен в 0xFFFFFFFFFFFF9ACE!
Может кто-нибудь помочь? Я часами работал над функцией, которая не делает ничего, кроме как эффективно генерирует случайный подписанный BIGINT, я устал, и чем больше я смотрю на эти вещи, тем больше я расстраиваюсь и тем меньше смысла в этом . Любая помощь, будь то объяснение того, что здесь происходит, или совет по написанию этой функции, чтобы она постоянно работала сейчас, и, если это ошибка, в более поздней версии, если она будет исправлена, будет принята с благодарностью!