如何通过 SnowSQL 或 Java 函数将十六进制 'F933F177' 转换为十进制 -114.036361?

How Can I Convert Hex 'F933F177' to Decimal -114.036361 via SnowSQL or a Java function?

我在 HEX 中存储了坐标,从网上搜索来看,它似乎使用了带符号的 2 的补码来处理负值。我对进行各种转换的位置有点迷茫,我认为路径应该是:

  1. 将十六进制转换为二进制。
  2. 将二进制转换为带符号的 2 的补码(有效地反转带符号的 2 的补码)。
  3. 转换为十进制
  4. 除以 1,000,000

我离这个过程还有多远?

我正在使用 Snowflake,因此我可以使用 SnowSQL 或 Java 联结来获得所需的结果。我不熟悉十六进制和带符号的 2 的补码。

如何对十六进制值 F933F177 进行逆向工程以获得十进制值 -114.036361?

包装来自 user16320675's comment using inline JAVA UDF 的代码:

create function transform_number(num varchar)
returns double
language java
handler='Test.transform_number'
target_path='@~/Test.jar'
as
$$
    class Test {
        public static double transform_number(String num) {
          return Integer.parseUnsignedInt(num, 16) / 1_000_000.0;
        }
    }
$$;

函数调用:

SELECT transform_number('F933F177') AS result;

输出:

我喜欢 Lukasz Java 回答 - 很简单。

这里有一个纯 SQL 答案,如果您想要纯 SQL 可以使用它 - 它还有助于理解完成此转换的过程:

select 'F933F177' s
    , to_number(s,'XXXXXXXX') n
    , length(s) l
    , pow(2, l/2*8) maxn
    , iff(n>maxn/2-1, n-maxn, n) n2
    , n2/1000000 n3 

作为 SQL UDF:

create or replace function signed_two_compliment(s varchar)
returns float
as $$
select n3 
from (
    select to_number(s,'XXXXXXXX') n
        , length(s) l
        , pow(2, l/2*8) maxn
        , iff(n>maxn/2-1, n-maxn, n) n2
        , n2/1000000 n3 
)
$$
;