在PL / SQL中移位位的正确方法

时间:2016-02-19 11:36:31

标签: oracle hex

我有一个64位整数id,我想显示最左边的32位。这可以使用Shift operators in PL/SQL完成。

实际上,这两行给出了相同的结果:

-- 1- not using a hex mask
select to_char(id / power(2, 32), 'XXXXXXXXXXXXXXXX', 'XXXXXXXX') from dual;

-- 2- using a hex mask
select to_char( bitand(id, to_number('ffffffff00000000', 'XXXXXXXXXXXXXXXX') / power(2, 32), 'XXXXXXXXXXXXXXXX', 'XXXXXXXX') from dual;

但是,我不明白为什么第一行有效,因为id未转换为十六进制或二进制。

似乎没有必要使用位掩码,但我不明白为什么。

没有它,是不是意味着十进制数除以2^32?在某些情况下,这不应该给出浮动数字吗?

由于

1 个答案:

答案 0 :(得分:2)

  

我真的不明白为什么六角面具是不必要的。

嗯,我真的不知道怎么解释这个,我会试着用一个例子。

第一个命令只取一个数字并将其除以power(2, 32) 这相当于将数字向右移动32位。

如果要将数字向右移1位,只需将其除以2即可
要将数字向右移2位,请将其除以2 * 2(power(2,2)) 要将数字向右移3位,请将其除以2 * 2 * 2(power(2,3)) ......
要将数字向右移32位,请将其除以2 * .... * 2(power(2,32))。


一些简单的例子 - 假设我们有一个数字12345(十进制) 12345(十进制)= 10011010010(二进制)
如果我们将这个数字向右移动1,2,3,4位,我们应该得到:

+-----+------------------+------------------+
| bit | result binary    | result decimal   |
+-----+------------------+------------------+
| 0   | 11000000111001   | 12345            |
| 1   |  1100000011100   |  6172            |
| 2   |   110000001110   |  3086            |
| 3   |    11000000111   |  1543            |
| 4   |     1100000011   |   771            |
+-----+------------------+------------------+

如果我们运行此查询:

select 12345 / power(2, 0) x0,
       12345 / power(2, 1) x1,
       12345 / power(2, 2) x2,
       12345 / power(2, 3) x3,
       12345 / power(2, 4) x4
FROM dual;

我们得到这些结果(十进制数字):

        X0         X1         X2         X3         X4
---------- ---------- ---------- ---------- ----------
     12345     6172.5    3086.25   1543.125   771.5625 

如果取这些结果的整数部分(在点之前)并将它们转换为二进制表示法,您将从上表中获得移位数字。

-----------编辑------------------

  

为什么选择to_char(13/2,'XXXXXXXX')从双给7而不是6.5?

因为to_char函数因格式XXXXX而舍入结果 请参阅文档:https://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements004.htm#i34510

  

<强> XXXX

     

返回指定位数的十六进制值。 如果   指定的数字不是整数,然后Oracle数据库对其进行舍入   到整数。


以下命令给出6.5

select 13 / 2 from dual;

下面的命令给出了7,7,6,因为to_char函数由于使用了XXXXX格式而将数字舍入为整数:

select to_char( 13 / 2, 'XXXXX' ),
       to_char( 6.5, 'XXXXX' ),
       to_char( 6.4, 'XXXXX' )
from dual;

TO_CHAR(13/2,'XXXXX') TO_CHAR(6.5,'XXXXX') TO_CHAR(6.4,'XXXXX')
--------------------- -------------------- --------------------
     7                     7                    6