Representing Binary or Hexadecimal Numbers

QUESTION: I have a number and I would like to see it expressed in both a binary and hexadecimal representation. How can I do that in IDL?

ANSWER: To express a byte, integer, or long integer number in a binary representation, you can use this little function I wrote named Binary. The code is quite simple:

FUNCTION BINARY, number

; This function returns the binary representation
; of byte, integer, and long integer numbers.
   
   ; What kind of number is this?

thisType = Size(number, /Type)

CASE thisType OF

   1: BEGIN ; Byte value
   
      bin = STRARR(8)
      FOR j=0,7 DO BEGIN
         powerOfTwo = 2L^j
         IF (LONG(number) AND powerOfTwo) EQ powerOfTwo THEN $
            bin(j) = '1' ELSE bin(j) = '0'
      ENDFOR
      ENDCASE
      
   2: BEGIN ; Integer value.

      bin = STRARR(16)
      FOR j=0,15 DO BEGIN
         powerOfTwo = 2L^j
         IF (LONG(number) AND powerOfTwo) EQ powerOfTwo THEN $
            bin(j) = '1' ELSE bin(j) = '0'
      ENDFOR
      ENDCASE

   3: BEGIN ; Long integer value.
   
      number = LONG(number)
      bin = STRARR(32)
      FOR j=0,31 DO BEGIN
         powerOfTwo = 2L^j
         IF (LONG(number) AND powerOfTwo) EQ powerOfTwo THEN $
            bin(j) = '1' ELSE bin(j) = '0'
      ENDFOR
      ENDCASE
      
   ELSE: ok = Dialog_Message('Only BYTE, INTEGER, and LONG values allowed.')
  
ENDCASE

RETURN, Reverse(bin)
END

To see an example of how to use the Binary program, type this:

   IDL> value = 53B
   IDL> Print, Binary(value)
      0 0 1 1 0 1 0 1

   IDL> value = 53
   IDL> Print, Binary(value)
      0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 1

   IDL> value = 53L
   IDL> Print, Binary(value)
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 1

Better Solution

Eddie Haskel (haskell@ccpo.odu.edu) of Old Dominion University writes to tell me that I am using way too much code in this program and that I should know better than to use FOR loops. He suggests this alternative, which has the advantage of returning a byte array instead of a string array.

FUNCTION BETTER_BINARY, number

; This function returns the binary representation
; of byte, integer, and long integer numbers.

   ; What kind of number is this?

thisType = Size(number, /Type)
IF thisType LT 1 OR thisType GT 3 THEN $
   ok = Dialog_Message('Only BYTE, INTEGER, and LONG values allowed.')
RETURN, Reverse( (number AND 2L^Lindgen( 2^thisType*4) ) NE 0)
END

Best Solution (?)

No posting seems to give me as much grief as one that has some kind of AND or OR statement in it. I must be wired wrong to appreciate binary arithmetic, is how I have it figured. :-(

In any case, Kevin Ivory (Kevin.Ivory@linmpi.mpg.de) offers this version of the Binary program, which he says:

... has the great advantage of additionally being able to show the binary representation of floats (this was quite important before IDL 5.1 got all these fancy keywords to the OPEN procedure). Something else I also concentrated on later in my own version, was to make the function work for arrays. [The Binary routine] now works for all numerical types and for arrays. It returns the same results on little and big-endian machines.

Here is the code, which has been modified by Ben Tupper to accept all manner of IDL integers, even 64-bit ones.

function binary, number
;+
; Name:
;   binary
; Purpose:
;   Returns the binary representation of a number of any numerical type.
; Argument:
;   number		scalar or array of numbers (any numerical type)
; Returns:
;   Byte array with binary representation of numbers.
; Examples:
;   Binary representation of 11b:
;     IDL> print, binary(11b)
;     0 0 0 0 1 0 1 1
;   Binary representation of pi (x86: Little-endian IEEE representation):
;     IDL> print, format='(z9.8,5x,4(1x,8i1))', long(!pi,0), binary(!pi)
;      40490fdb      01000000 01001001 00001111 11011011 (x86 Linux)
;      0fdb4149      00001111 11011011 01000001 01001001 (Alpha OpenVMS)
;     IDL> print, format='(8(1x,8i0))', binary(!dpi)
;      01000000 00001001 00100001 11111011 01010100 01000100 00101101 00011000
;   Some first tests before type double was added:
;     print, format='(2a6,4x,2z9.8,4x,8z3.2)', $
;       !version.arch, !version.os, long(!dpi,0,2), byte(!dpi,0,8)
;       x86 linux     54442d18 400921fb     18 2d 44 54 fb 21 09 40
;     sparc sunos     400921fb 54442d18     40 09 21 fb 54 44 2d 18
;     alpha   vms     0fda4149 68c0a221     49 41 da 0f 21 a2 c0 68
;     (Beginning with IDL 5.1, Alpha VMS uses IEEE representation as well.)
; Modification history:
;    19 Dec 1997	Originally a news posting by David Fanning.
;                       (Re: bits from bytes)
;    20 Dec 1997	"Complete" rewrite: eliminate loops.
;    22 Dec 1997	Bit shift instead of exponentiation, return byte
;			array, handle input arrays.
;			Think about double and complex types.
;    22 Sep 1998	Complete rewrite: reduce every numerical type to
;			single bytes. Check that big and little endian machines
;			return exactly the same results (if IEEE).
;    7 May 2003		Added newish data types, unsigned and long64.  BT
;-
  s = size(number)
  type = s[s[0] + 1]
  n_no = s[s[0] + 2]
; Numerical types: (will have to be completed if IDL adds double-long, ...)
; 1: byte             (1-byte unsigned integer)
; 2: integer          (2-byte   signed integer)
; 3: long             (4-byte   signed integer)
; 4: floating-point   (4-byte, single precision)
; 5: double-precision (8-byte, double precision)
; 6: complex        (2x4-byte, single precision)
; 9: double-complex (2x8-byte, double precision)
; 12: uInt	    (2-byte, unsigned integer)
; 13: uLong	    (4-byte, unsigned integer)
; 14: Long64	    (8-byte, signed integer)
; 15: uLong64	    (8-byte, unsigned integer)  
; Non-numerical types:
; 0: undefined, 7: string, 8: structure, 10: pointer, 11: object reference
;  nbyt = [0, 1, 2, 4, 4, 8, 8, 0, 0, 16, 0, 0] ; number of bytes per type
; code = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
  nbyt = [0, 1, 2, 4, 4, 8, 8, 0, 0, 16, 0, 0,  2,  4,  8,  8]
  ntyp = nbyt[type]
  if ntyp eq 0 then message, 'Invalid argument (must be numerical type).'
  bits = [128, 64, 32, 16,  8,  4,  2,  1] ; = ishft(1b, 7-indgen(8))
; For correct array handling and byte comparison, 'number' and 'bits' require
; same dimensions -> numvalue and bitvalue
  bitvalue = ((bits)[*, intarr(ntyp)])[*, *, intarr(n_no)]
  little_endian = (byte(1, 0, 1))[0]
; In case of complex type and little endian machine, swap the two float values
; before the complete second dimension is reversed at returning.
  if (type eq 6 or type eq 9) and little_endian then $ ; type complex
    numvalue = reform((byte([number], 0, 1, ntyp/2, 2, n_no))$
                      [intarr(8), *, [1,0], *], 8, ntyp, n_no) $
  else numvalue = (byte([number], 0, 1, ntyp, n_no))[intarr(8), *, *]
; On little endian machines, the second dimension of the return value must
; be reversed.
  if little_endian and (type ne 1) then $
    return, reverse((numvalue and bitvalue) ne 0, 2) else $
    return,         (numvalue and bitvalue) ne 0
end

Representing Hexadecimal Numbers

To represent hexadecimal numbers, use the Format keyword to the Print command with the "Z" format, like this:

   IDL> values = Indgen(32)
   IDL> Print, values, Format='( 16( Z2.2, x) )'
      00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
      10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f

Google
 
Web Coyote's Guide to IDL Programming