やあ、これはバグかもしれないと思うが、それは私を殺している. Ubuntu Linux サーバーで MySQL 5.1.41 を使用しています。ランダムな符号付き BIGINT 値を作成する関数を作成しようとしています。RAND() の精度は小さすぎて可能な BIGINT 値の全範囲を生成できないため、ビット演算子を使用して 4 つの 32 ビット ワードを結合することにしました。
MySQL Workbench を起動し、次のことを試して、ビット シフト演算子が負の数で正しく機能するかどうかを確認しました。
SELECT HEX((0x1ACE - 0x8000) << 0x10);
0x1ACE - 0x8000 は -25906 なので、16 ビットを左にシフトすると、65536 を乗算する必要がありますよね? 返された答えは 0xFFFFFFFF9ACE0000 で、これは -1697775616 または -25906 * 65536 の符号付き表現です。
そこで私の計画は、それを使用してランダムな符号付き BIGINT の最初の 32 ビット ワードを生成し、単純なループを使用して値にさらに 32 ビット ワードを 3 つ追加し、一度に 4 バイト以上ビットをシフトすることでした。興奮して、最初に次のコードを関数に入れ、ハードコードされた値を使用して計画をテストしました。
DECLARE x BIGINT;
SET x = (0x1ACE - 0x8000) << 0x10;
シフトされる値が正になるように値を設定すると、すべて正常に動作します。ただし、シフトされた負の値 (この場合は -25906) を使用してこの計算を実行した後、x が 0x7FFFFFFFFFFFFFFF であることがわかりました。これは、符号付き 64 ビット整数の正の最大値です。私は完全に困惑しています。まったく同じ操作が、関数内の SET 操作であるか、SELECT ステートメントであるかによって、まったく異なる結果を生成しています。
そのため、x が署名されているか署名されていないかをいじり始めたところ、事態は非常に奇妙になりました。x unsigned を作ってみて、次のことを試しました:
DECLARE x BIGINT UNSIGNED;
SET x = (0x1ACE - 0x8000);
私がそれをしたとき、私はゼロに等しい x を得ました。x は符号なしであり、結果は負であるため、驚くことではありません。しかし、ひばりで、私はこれを試しました:
DECLARE x BIGINT UNSIGNED;
SET x = (0x1ACE - 0x8000) << 0;
驚いたことに、x は 0xFFFFFFFFFFFF9ACE に設定されていました。
誰か助けてくれませんか?私はランダムな符号付き BIGINT を効率的に生成するだけの関数に何時間も取り組んできました。私は疲れています。このようなものを見れば見るほど、イライラが増し、理解できなくなります。 . ここで何が起こっているのかを説明したり、この関数を記述して現在一貫して機能するようにアドバイスしたり、これがバグである場合は修正された場合は後のバージョンでサポートしたりしていただければ幸いです。