我启动了MySQL Workbench,并尝试了以下内容,看看位移运算符是否与负数一起正常工作:
SELECT HEX((0x1ACE - 0x8000) << 0x10);
0x1ACE - 0x8000是-25906,所以如果我向左移16位,我应该乘以65536,对吧?我得到的答案是0xFFFFFFFF9ACE0000,这是-1697775616的签名表示,或-25906 * 65536. Wunderbar,它的工作原理!!!
所以我的计划是使用它来生成随机签名BIGINT的第一个32位字,并使用一个简单的循环向该值添加三个32位字,一次将位移到四个字节。兴奋地,我开始将以下代码放在我的函数中,使用硬编码值来测试我的计划:
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之外什么也没做,我很累,而且我越看这些东西,我越沮丧,我越不能理解它。任何帮助,无论是在解释这里发生了什么或建议写这个功能,以便它现在一贯工作,如果这是一个错误,在以后的版本,如果它得到修复,将不胜感激!
答案 0 :(得分:2)
好吧,我想我只想出来了。根据{{3}},位移运算符导致无符号 64位整数。所以当你尝试:
DECLARE guid BIGINT; -- signed BIGINT
SET guid = -25924; -- = 0xFFFFFFFFFFFF9ABC
SET guid = guid << 0; -- Result: 0x7FFFFFFFFFFFFFFF
正在发生的事情是为了guid&lt;&lt; 0返回一个无符号整数,它试图将guid从负有符号整数转换为无符号整数,产生0x7FFFFFFFFFFFFFFF,然后将其转移到零位,这是一个导致相同的标识操作0x7FFFFFFFFFFFFFFF。
然而,乘法(*)似乎可以在有符号和无符号数上正确工作。我可以通过以下方式实现我想要的结果:
DECLARE guid BIGINT; -- signed BIGINT
SET guid = -25924; -- = 0xFFFFFFFFFFFF9ABC
SET guid = guid * 0x10000; -- = Result: 0xFFFFFFFF9ABC0000 Woot! \o/