您好,我有一个名为Hexchar的SAS字符列,其中包含十六进制字符“ 0x1ba0c56c966ee8b0000”,实际上是十进制数8154350000000000000000。我想将“ 0x1ba0c56c966ee8b0000”转换为8154350000000000000000。如果十六进制数小于16个字节,则以下函数可以完成此工作。
DexNumber=input(substr(Hexchar,3), hex16.); /* The reason why substr() function is to skip "0x" in the front */
但是,十六进制格式仅限于16个字节,不能处理更多字节。您知道将其转换为任何好的逻辑吗?
答案 0 :(得分:2)
您将无法在SAS数字(64位双精度)中精确存储如此大的整数。
来自https://v8doc.sas.com/sashtml/win/numvar.htm
Windows下SAS变量的有效位数和长度最大的整数
| Length | Largest Integer | Exponential
| (Bytes) | Represented Exactly | Notation
+---------+-----------------------+------------
| 3 | 8,192 | 2 ^ 13
| 4 | 2,097,152 | 2 ^ 21
| 5 | 536,870,912 | 2 ^ 29
| 6 | 137,438,953,472 | 2 ^ 37
| 7 | 35,184,372,088,832 | 2 ^ 45
| 8 | 9,007,199,254,740,992 | 2 ^ 53
因此,尽管C
中的所有16位十六进制值都可以明显地适合于64位整数,但并非所有这些都可以明显地适合于SAS数字(那些> 2**53
)。 64位double是IEEE标准,尽管精度有所下降,但可以处理高达10 ** 51的数字。
此代码显示两个不同的大整数分配存储为与分配的值不同的相同SAS数值。
data _null_;
x = 837886600861902976;
y = 837886600861902977;
put x= 20. / y= 20.;
if x=y then put 'Huh? Ooohhh.';
run;
---------------------
x=837886600861902848
y=837886600861902848
Huh? Ooohhh.
一种方法是将c-hex字符串分成“上”和“下”部分,并用它们的输入执行算术运算。需要注意的是,当实际的十六进制值大于2 ** 53时,将会失去清晰度/精度。
data _null_;
length H $30;
input H;
put h=;
if H =: '0x' then do;
HX = substr(H,3); * skip over 0x;
if (length (HX) > 15) then do;
HX_lower = substr(HX, length(HX)-14);
HX_upper = substr(HX, 1, length(HX)-15);
if length (HX_lower) > 15 then put 'ERROR: ' H= 'too big for two parts';
H_lower = input (HX_lower,hex15.);
H_upper = input (HX_upper,hex15.);
U = H_upper * 16**15;
L = H_lower;
put / H;
put HX_upper $16. ' ->' H_upper 20. ' ->' U 25.;
put HX_lower $16. ' ->' H_lower 20. ' ->' L 25.;
H_num = U + L;
end;
else do;
H_num = input (HX, hex15.);
end;
end;
else
put 'ERROR: ' H= 'is not c hex';
put H= H_num= comma30.;
datalines;
0x1
0x1b
0x1ba
0x1ba0
0x1ba0c
0x1ba0c5
0x1ba0c56
0x1ba0c56c
0x1ba0c56c9
0x1ba0c56c96
0x1ba0c56c966
0x1ba0c56c966e
0x1ba0c56c966ee
0x1ba0c56c966ee8
0x1ba0c56c966ee8b
0x1ba0c56c966ee8b0
0x1ba0c56c966ee8b00
0x1ba0c56c966ee8b000
0x1ba0c56c966ee8b0000
magic!
run;
答案 1 :(得分:0)
通过了解这些精度问题,以下是我自己的转换逻辑。
data test;
长度为dum_s $ 24。
dum_s =“ 1ba0c56c966ee8b0000”;
do while(length(dum_s)<24);
dum_s="0"||dum_s;
end;
dum_dec1=input(substr(dum_s,1,8),hex8.);
dum_dec2=input(substr(dum_s,9,8),hex8.);
dum_dec3=input(substr(dum_s,17,8),hex8.);
dum1=dum_dec1*16**16;
dum2=dum_dec2*16**8;
dum3=dum_dec3*16**0;
dum=dum1+dum2+dum3;
dum_ether=dum/10**18;
放入dum_ether;
运行;
以太坊交易哈希0x57662d92cb24943079dec7d83d3c39fc7a1ae958b22de58ba62c8c4cb425cab3 它的值是基于六进制的“ 0x1ba0c56c966ee8b0000”,我的上述逻辑给了我8154.35以太坊(10 ** 18倍为wei),与该站点相同。 https://etherscan.io/tx/0x57662d92cb24943079dec7d83d3c39fc7a1ae958b22de58ba62c8c4cb425cab3 当值变成浮点数时,我会意识到一些精度问题。
谢谢!