BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
linlin87
Quartz | Level 8

Hi SAS Communities


I have a question. I have a hexidecimal value (for example 20 e9 ef 01), but I need to convert this to little endian format first (byte swapping) before I can get the decimal number. For this examples it would be that hexadecimal 20 e9 ef 01 is converted to little endian of 01 EF E9 20 which can then be converted to integer of 32500000 (UINT32). How do I do this process in SAS?

I have following

 

data test;
set indata;
format tab hex8.;
lit_end=input(tab,$UCS2LEw.);
run;

I assumed simply applying new informat of little endian would convert hexidecimal to little endian format. But it show:


ERROR 48-59: The informat UCS2LEW was not found or could not be loaded.

 

I wonder if other way to do?

 

Any help would be very great.

1 ACCEPTED SOLUTION

Accepted Solutions
mkeintz
PROC Star

@linlin87 wrote:

Thanks mkeintz for explaining, very useful. How do I pass a character string to this process? For example I have the character variable value which takes values like 80f8d501. How do I pass this rather than the txt= example you gave above?

 

 

data input;
set input;
put value;
z=input(value,ib4.);
put value= value=hex8. z=;
run;

and the log reads for the first row of data

 

 

80f8d501
value=80f8d501 value=38306638 z=946221112

I was expecting z to read 30800000.

 

Any help would be great!

 

Your value variable is apparently eight bytes long (value='80f8d501').   This is equivalent to 16 nibble's, which have a one-to-one correspondence with hexadecimal digits.  Using the IB4 informat in the input function reads the first 4 bytes, i.e. the first 8 nibbles.  So for your situation, it is converting hexadecimal 38306638 to an integer, not hexadecimal 80f8d501.   For instance, the first character '8' is stored as '38'x, which is '00110110' binary.

806  data _null_;
807    value='80f8d501';   /* 8 bytes long */
808    put value=hex16.;   /* Write 8 bytes as 16 nibbles */
809  run;

value=3830663864353031

So if you can't go back and read in VALUE as a 4-character (i.e. 4 bytes = 8 nibbles) variable, then you need to create an intermediate four-byte variable which is truly '80f8d501' hexadecimal:

 

860  data _null_;
861    value='80f8d501';   /* 8 bytes long */
862    put value=  ' equivalent in hexadecimal to ' value hex16. ;
863
864    length hexvalue $4;
865    hexvalue=input(value,$hex8.);
866    z=input(hexvalue,ib4.);
867    put hexvalue=hex8. z=;
868  run;

value=80f8d501  equivalent in hexadecimal to 3830663864353031
hexvalue=80F8D501 z=30800000

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------

View solution in original post

4 REPLIES 4
mkeintz
PROC Star

@linlin87 wrote:

Hi SAS Communities


I have a question. I have a hexidecimal value (for example 20 e9 ef 01), but I need to convert this to little endian format first (byte swapping) before I can get the decimal number. For this examples it would be that hexadecimal 20 e9 ef 01 is converted to little endian of 01 EF E9 20 which can then be converted to integer of 32500000 (UINT32). How do I do this process in SAS?

Any big endian hexadecimal number that ends in "01"  (such as 20e9ef01) cannot generate an even integer value (such as 32500000).  

 

But on my little-Endian intel machine, the hexadecimal value 20E9Ef01 becomes 32500000 using the IB4.  format.

 

708  data _null_;
709    length txt $4;
710    txt='20E9Ef01'x;
711    z=input(txt,ib4.);
712    put txt=$hex8. z=;
713  run;

txt=20E9EF01 z=32500000

In other words, your initial value appears to be little endian already.  

 

Now if your data really does start out as big endian, and you are processing it on a little endian machine, then

778  data _null_;
779    length bigendian $4;
780    bigendian='01EFE920'x;
781    ZBIG=input(bigendian,s370fpib4.);
782    put bigendian=$hex8. ZBIG=;
783  run;

bigendian=01EFE920 ZBIG=32500000

Take a look at Byte Ordering for Integer Binary Data on Big Endian and Little Endian Platforms

 

As you can see, I assume you don't really need to reverse byte order, but you do need to know want informat to use to read the data given its "endian" attribute.

 

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
linlin87
Quartz | Level 8

Thanks mkeintz for explaining, very useful. How do I pass a character string to this process? For example I have the character variable value which takes values like 80f8d501. How do I pass this rather than the txt= example you gave above?

 

 

data input;
set input;
put value;
z=input(value,ib4.);
put value= value=hex8. z=;
run;

and the log reads for the first row of data

 

 

80f8d501
value=80f8d501 value=38306638 z=946221112

I was expecting z to read 30800000.

 

Any help would be great!

 

mkeintz
PROC Star

@linlin87 wrote:

Thanks mkeintz for explaining, very useful. How do I pass a character string to this process? For example I have the character variable value which takes values like 80f8d501. How do I pass this rather than the txt= example you gave above?

 

 

data input;
set input;
put value;
z=input(value,ib4.);
put value= value=hex8. z=;
run;

and the log reads for the first row of data

 

 

80f8d501
value=80f8d501 value=38306638 z=946221112

I was expecting z to read 30800000.

 

Any help would be great!

 

Your value variable is apparently eight bytes long (value='80f8d501').   This is equivalent to 16 nibble's, which have a one-to-one correspondence with hexadecimal digits.  Using the IB4 informat in the input function reads the first 4 bytes, i.e. the first 8 nibbles.  So for your situation, it is converting hexadecimal 38306638 to an integer, not hexadecimal 80f8d501.   For instance, the first character '8' is stored as '38'x, which is '00110110' binary.

806  data _null_;
807    value='80f8d501';   /* 8 bytes long */
808    put value=hex16.;   /* Write 8 bytes as 16 nibbles */
809  run;

value=3830663864353031

So if you can't go back and read in VALUE as a 4-character (i.e. 4 bytes = 8 nibbles) variable, then you need to create an intermediate four-byte variable which is truly '80f8d501' hexadecimal:

 

860  data _null_;
861    value='80f8d501';   /* 8 bytes long */
862    put value=  ' equivalent in hexadecimal to ' value hex16. ;
863
864    length hexvalue $4;
865    hexvalue=input(value,$hex8.);
866    z=input(hexvalue,ib4.);
867    put hexvalue=hex8. z=;
868  run;

value=80f8d501  equivalent in hexadecimal to 3830663864353031
hexvalue=80F8D501 z=30800000

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
Tom
Super User Tom
Super User

If the value is already encoded into a hex string then use the $HEX informat to convert the hex string back into an actual string.

55    data _null_;
56      txt='80f8d501';
57      x=input(input(txt,$hex8.),ib4.);
58      put txt = x=comma20.;
59   run;

txt=80f8d501 x=30,800,000
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 4 replies
  • 501 views
  • 0 likes
  • 3 in conversation