Our World Statistics Day conversations have been a great reminder of how much statistics can inform our lives. Do you have an example of how statistics has made a difference in your life? Share your story with the Community!
Choose Language Hide Translation Bar
All your base are belong to us (in JSL)

Converting a value from one base or radix to another is often required with data in external formats such as sensor or network data. JMP has supported converting from hexadecimal to decimal and back using the Hex and Hex to Number functions. For example:

decimalToHex = Hex(1234, “integer”);
show(decimalToHex);
backToDecimal = HexToNumber(decimalToHex);
show(backToDecimal);

Output:

 

decimalToHex = "000004D2";
backToDecimal = 1234;

 

But what if you have binary or octal data?

Not just hex anymore

With JMP 15, these functions have been expanded to support any base from 2 to 36. By specifying the Base option on the Hex function, the decimal number will be converted to that base rather than the default base of 16.

decimalToBinary = Hex(1234, Base(2));
show(decimalToBinary);
decimalToOctal = Hex(1234, Base(8));
show(decimalToOctal);

Output:

 

decimalToBinary = "10011010010";
decimalToOctal = “2322”

 

Often with binary data, you want the values to be padded to byte boundaries for consistency. The new Pad To option allows that.

Padded to 2-bytes:

Hex(1234, Base(2), Pad To(16));

 

"0000010011010010"

 

Padded to 4-bytes:

Hex(1234, Base(2), Pad To(32));

 

"00000000000000000000010011010010"

 

Hex To Number provides the reverse functionality when the Base option is specified.

Convert from binary to decimal:

binaryToDec = Hex To Number("10011010010", Base(2));
show(binaryToDec);
octalToDec = Hex To Number("2322", Base(8));
show(octalToDec);

Output:

 

binaryToDec = 1234;
octalToDec = 1234;

QR Codes

QR codes (Quick Response codes) are two-dimensional bar codes that store small amounts of binary data that can be read using a scanner or smartphone. These codes were developed for inventory tracking, but they are often used now to encode location data for websites or applications. For example, here is a QR code for the JMP Discovery Summit in Tucson that links to the main web page of the conference.

 

QR Code for Discovery Summit Tucson 2019QR Code for Discovery Summit Tucson 2019

The QR code consists of several fixed patterns (such as the three large square blocks for alignment) and the cell/content area for the data plus the error detection/correction information. QR codes come in a variety of sizes and have varying levels of error correction. Those details are not important for this exercise.

Let’s imagine that you wanted to encode the URL for Discovery Summit Tucson 2019 into the bits needed for a QR code.

We can start with the URL:

https://discoverysummit.jmp/en/2019/usa/home.html

QR codes support four types of encoding: Numeric, Alphanumeric, Byte and Kanji. Since our URL is a combination of letters, numbers and symbols, we can use the Alphanumeric encoding. Alphanumeric coding only supports uppercase letters, but that’s OK since the URL is case-insensitive.

Unfortunately, the QR encodings for characters aren’t just the ASCII values. If they were, we could just use the Hex function to get the encoding. Instead, we will write a short JSL function to do the conversion based on the table below.

 

Letter

Code

ASCII

Letter

Code

ASCII

Letter

Code

ASCII

0

0

48

F

15

70

U

30

85

1

1

49

G

16

71

V

31

86

2

2

50

H

17

72

W

32

87

3

3

51

I

18

73

X

33

88

4

4

52

J

19

74

Y

34

89

5

5

53

K

20

75

Z

35

90

6

6

54

L

21

76

Space

36

32

7

7

55

M

22

77

$

37

36

8

8

56

N

23

78

%

38

37

9

9

57

O

24

79

*

39

42

A

10

65

P

25

80

+

40

43

B

11

66

Q

26

81

-

41

45

C

12

67

R

27

82

.

42

46

D

13

68

S

28

83

/

43

47

E

14

69

T

29

84

:

44

58

 

Here is the JSL function to do the conversion from a character to the alphanumeric encoded value.

encodeAlpha = Function( {ch},
    // Convert character to its ASCII number value.
    hexVal = Hex To Number(Hex(ch));
    // Map the ASCII value to the QR encoded value.
    If(hexVal >= 48 & hexVal <= 57, hexVal - 48, // 0-9
       hexVal >= 65 & hexVal <= 90, hexVal - 55, // A-Z
       hexVal >= 97 & hexVal <= 122, hexVal - 87,// a-z
       hexVal == 32, 36,                         //Space
       hexVal >= 36 & hexVal <= 37, hexVal + 1,  // $ %
       hexVal >= 42 & hexVal <= 43, hexVal - 3,  // * +
       hexVal >= 45 & hexVal <= 47, hexVal - 4,  // - . /
       hexVal == 58, 44,                         // :
       0;
    );
);

The If statement maps the ASCII value to the encoded value using ranges. For example, the characters 0-9 are ASCII 48-57 and are encoded as 0-9. Therefore, those can be transformed from ASCII by simply subtracting 48. There are similar ranges for A-Z and a-z. The lowercase a-z are mapped to the values for the uppercase A-Z. The symbols jump around, so most are handled on an individual basis.

To save space, the QR code doesn’t directly write out the encoded value. It breaks the string into pairs of characters. For our URL, it would look like this:

ht tp s: // di sc ov er ys um mi t. jm p/ en /2 01 9/ us a/ ho me .h tm l

For each pair of characters, the encoded value for the first character is multiplied by 45 and added to the encoded value of the second character.

Our first pair is ‘ht’:

H = 17

T = 29

The result would be 17 * 45 + 29 = 794. This is then converted into an 11-bit binary value which is padded with zeros if necessary.

749 = 01011101101

If there is an odd number of characters, as in our case, the last character is just encoded and converted to a 6-bit binary value. In our case, we have a single ‘l’ at the end.

L = 21

21 = 010101

Converting numbers to binary and applying padding is exactly what the Hex function can do now. Let’s start by writing a function to calculate the encoded number for a pair of characters.

encodePair = Function ( {pair},
    char1 = Substr(pair, 1, 1);
    char2 = Substr(pair, 2, 1);
    encode1 = If(Length(pair) == 1, 0, encodeAlpha(char1));
    encode2 = If(Length(pair) == 1, encodeAlpha(char1),
                                    encodeAlpha(char2));
    encode1 * 45 + encode2;	
); 

Now we can encode each pair from our URL to create the data for our QR code.

qrData = "";
For( i = 1, i <= Length( url ), i = i + 2,
    charPair = Substr( url, i, 2 );
    encodedValue = encodePair(charPair);
    asBinary = If(Length(charPair) == 1, 
           Hex(encodedValue, Base( 2 ), Pad To (6)),
           Hex(encodedValue, Base( 2 ), Pad To (11));
    );
    qrData = qrData || asBinary || " ";
);

show(qrData);

In this JSL, two characters are taken from the URL with each pass of the For loop and the alphanumeric encoding is calculated on that pair. The Hex function converts the number to its binary representation. The value is padded to either 11-bits or 6-bits depending on whether there are 1 or 2 characters. The binary value is appended to the previous value. We added a space between the pairs to make the output easier to read. The space wouldn’t be included in the actual QR data.

Here is the result for the URL:

 

qrData = "01100011010 10100110010 10100011000 11110111010 01001011011 10011111000 10001010111 01010010001 11000010110 10101011100 01111110000 10101000011 01101101101 10010010000 01010001101 11110010001 00000000001 00111000000 10101100010 00111101101 01100010101 01111101100 11101110011 10100101111 010101 ";

 

There is a lot more that goes into creating the final output for a QR code like the encoding mode, the character count indicator, and error correction coding. That’s more than we need to cover to show the new features. Hopefully, this helped explain some of the new Hex and Hex To Number features and how they can be applied.