Преобразование шестнадцатеричных символов (более 16 байтов) в десятичное число в SAS - PullRequest
0 голосов
/ 05 ноября 2018

Привет! У меня есть столбец символов SAS с именем Hexchar, содержащий шестнадцатеричный символ "0x1ba0c56c966ee8b0000". На самом деле это 8154350000000000000000 в десятичном формате. И я хочу преобразовать «0x1ba0c56c966ee8b0000» в 8154350000000000000000. Если шестнадцатеричный код меньше 16 байт, то следующая функция выполняет свою работу.

DexNumber=input(substr(Hexchar,3), hex16.); /* The reason why substr() function is to skip "0x" in the front */

Однако шестнадцатеричный формат ограничен только 16 байтами и не может обрабатывать больше байтов. Знаете ли вы хорошую логику, чтобы преобразовать это?

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Понимая эти проблемы точности, моя собственная логика преобразования приведена ниже.

data test;

длина дум_с $ 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;

put dum_ether;
бежать;

Хеш транзакции Ethereum 0x57662d92cb24943079dec7d83d3c39fc7a1ae958b22de58ba62c8c4cb425cab3 и его значение в шестнадцатеричном базисе "0x1ba0c56c966ee8b0000", и моя логика выше дает мне 8154,35 эфириума (10 ** 18 раз в вей), который совпадает с сайтом. https://etherscan.io/tx/0x57662d92cb24943079dec7d83d3c39fc7a1ae958b22de58ba62c8c4cb425cab3 Когда значение становится с плавающей запятой, возникают некоторые проблемы с точностью, о которых я должен знать.

Спасибо!

0 голосов
/ 05 ноября 2018

Вы не сможете хранить такие большие целые числа точно в числовой форме SAS (64-разрядное двойное число).

С https://v8doc.sas.com/sashtml/win/numvar.htm

Значимые цифры и наибольшее целое по длине для переменных SAS в Windows

| 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

Таким образом, хотя все 16-значные шестнадцатеричные значения в C могут отчетливо вписываться в 64-разрядное целое число, не все такие могут отчетливо вписываться в числовые значения SAS (те, которые> 2**53). Однако 64-битный дубль является стандартом 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...