Oracle十六进制到数字转换dword

时间:2014-12-04 23:17:41

标签: oracle

我正在尝试将十六进制转换为数字。如果我使用

SELECT To_Number('F8EF7F2C', 'xxxxxxxx')  FROM dual;

结果是4176445228.这是qword结果。

我想得到的是dword结果-118522068

我如何实现这一目标?

谢谢,

更新

SELECT to_number('F8EF7F2C', 'xxxxxxxxxx')-Power(2,32) FROM dual

似乎适用于此值'F8EF7F2C'。但是将十六进制值更改为

SELECT to_number('0208A5FA', 'xxxxxxxxxx')-Power(2,32) FROM dual

产生错误的结果-4260846086。正确的结果是34121210,由

生成
SELECT to_number('0208A5FA', 'xxxxxxxxxx') FROM dual

我可以在Dword程序员模式下验证PC计算器的正确结果。

1 个答案:

答案 0 :(得分:2)

据我所知,你的qword是无符号的32位整数,而dword是带符号的32位整数。

这是一个带有一些十六进制值的小测试:

with hex as (
   select '00000000' hex from dual union all
   select '0208A5FA' hex from dual union all
   select '7FFFFFFF' hex from dual union all
   select '80000000' hex from dual union all
   select 'F8EF7F2C' hex from dual union all
   select 'FFFFFFFF' hex from dual
)
select hex.hex
     , to_number(hex.hex,'XXXXXXXX') unsigned
     , case
          when to_number(hex.hex,'XXXXXXXX') >= power(2,31)
          then to_number(hex.hex,'XXXXXXXX') - power(2,32)
          else to_number(hex.hex,'XXXXXXXX')
       end signed
     , mod(
          to_number(hex.hex,'XXXXXXXX') + power(2,31)
        , power(2,32)
       ) - power(2,31) signed_alternative
  from hex
 order by hex.hex
/

查询的输出是:

HEX        UNSIGNED        SIGNED SIGNED_ALTERNATIVE
-------- ---------- ------------- ------------------
00000000          0             0                  0
0208A5FA   34121210      34121210           34121210
7FFFFFFF 2147483647    2147483647         2147483647
80000000 2147483648   -2147483648        -2147483648
F8EF7F2C 4176445228    -118522068         -118522068
FFFFFFFF 4294967295            -1                 -1

SIGNED的计算方式与@zerkms在评论中的建议相似,CASE表达式仅用于在2^32溢出时减去它。

SIGNED_ALTERNATIVE给出相同的结果,但首先添加2^31,然后取模2^32,然后再次减去2^31

CASE表达式可能会更有效率,因为它对这些NUMBER值执行的数值运算较少(如果它是浮点运算,模数版本可能会更快,因为它本来可以优化到位操作; - )