# How much faster is HEX versus decimal on the CoCo?

This is a topic I have mentioned in earlier articles about speeding up BASIC. I recently found one of my test programs and thought I’d update it a bit and share it.

A quick recap…

In BASIC, numbers in the program are stored as the characters. If you have “A=123” that “123” appears in the BASIC code as those characters. When the program RUNs, basic has to convert that series of characters to a number.

It takes more work to parse a standard base-10 (decimal, digits 0-9) set of characters to a number than it does to parse a base-16 (HEX, digits 0-F). To demonstrate, I wrote a very simple parser. It takes a string and converts it to a number, manually. (BASIC already has a VAL keyword that does this, but I wanted to show how it works.) Note this does not look for negative (“-“) or decimals or scientific notation – just a basic number like “12345”.

## Decimal String to Number

`10 ' STRTONUM.BAS20 LINE INPUT "TYPE A NUMBER: ";NM\$30 GOSUB 6040 PRINT "THE VALUE IS :";NM50 END60 ' CONVERT NM\$ TO NM NUMBER70 NM=0:ZM=180 ' SCAN FROM RIGHT TO LEFT90 FOR Z=LEN(NM\$) TO 1 STEP -1100 ' GET CHARACTER VALUE110 ZC=ASC(MID\$(NM\$,Z,1))120 ' EXIT IF NOT 0-9130 IF ZC>=ASC("0") THEN IF ZC<=ASC("9") THEN 160140 PRINT "NOT A NUMBER : ";NM\$150 RETURN160 ' SUBTRACT ASCII "0" AND MATH170 NM=NM+(ZC-ASC("0"))*ZM175 PRINT ZC-ASC("0"); "*";ZM;"=";NM180 ' 0, 10, 100, 1000, ETC.190 ZM=ZM*10200 NEXT210 RETURN`

If you have a number like “12345”, you start at the right-most ASCII character (“5”) and convert that to a number. You multiply that number by a multiplier that starts out as 1. So, “5 * 1 = 5”.

Then you multiply the multiplier by 10, so 1 becomes 1. You move to the next digit, “4”, and multiply it by the new multiplier. So, “4*10 = 40”. That is added to the previous value, so “5 + 40 = 45”.

The multiplier is multiplied by 10, so 10 becomes 100. The next digit is a “3”, so that becomes “3 * 100 = 300”. It is added to the sum – “300 + 45 = 345”.

Repeating, the multiplier is multiplied by 10 making it 1000. The next digit is a “2”, so that becomes “2 * 1000 = 2000”. That is added making “2000 + 345 = 2345”. I think we see the pattern.

After the multiplier is multiplied by 10 again, making it 10000, we go through this again with the final digit, the “1”. That makes “1 * 10000 = 10000” and that is added making “10000 + 2345 = 12345”.

Whew!

## HEX String to Value

But, with a hexadecimal value, the math gets much simpler since each character of a hex string represents a set of four bits in a byte. A similar converter is much smaller.

`10 ' STRTONUM.BAS20 LINE INPUT "TYPE A HEXNUM: ";NM\$30 GOSUB 6040 PRINT "THE VALUE IS :";NM50 END60 ' CONVERT NM\$ TO NM NUMBER70 NM=080 ' SCAN FROM LEFT TO RIGHT90 FOR Z=1 TO LEN(NM\$)100 ' GET CHARACTER VALUE110 ZC=ASC(MID\$(NM\$,Z,1))120 ' EXIT IF NOT 0-9 OR A-F130 IF ZC>=ASC("0") THEN IF ZC<=ASC("9") THEN 200140 IF ZC>=ASC("A") THEN IF ZC<=ASC("F") THEN 180150 PRINT "NOT A HEXNUM : ";NM\$160 RETURN170 ' CONVERT A-F TO 10-15180 ZC=ZC-(ASC("A")-(ASC("9")+1))190 ' NOW MAKE 0-15200 ZC=ZC-ASC("0")210 PRINT NM;"+";ZC;"=";220 NM=NM+ZC230 PRINT NM240 IF Z<LEN(NM\$) THEN NM=NM*16250 NEXT260 RETURN`

In BASIC, once it sees some characters starting with “&H”, it gets the value of the next character. If it is A-F, it subtracts from the value so it looks like the ASCII values after “0” to “9”.

Then it subtracts the ASCII of “0” so the value becomes 0-15.

If there is another character, it shifts this value four places to the left (multiply by 16 in the code above) and it moves on to the next digit and repeats.

Bit shifts (multiplying by power of 2) are much quicker than multiplying. It makes the whole parsing routine much faster.

## But how much faster?

I wrote this sample program which sits in a loop and sets a variable 10,000 times — first setting using a normal base-10 number (“A=1”), and then again using the HEX version (“A=&H1”). After each one it prints the TIMER value, and at the end of the line it prints how much faster (or slower) the HEX version was over decimal.

And as a bonus, at the end, it compares “A=.” (that is a fast shortcut for “A=0”) to “A=&H0” to show one case where there is something faster than HEX.

`10 'DECVSHEX2.BAS20 DIM A,I,TD,TH:MX=1000030 PRINT "DO NOT PRESS KEYS WHILE RUNNING"40 FOR I=1 TO 1000:NEXT I50 PRINT "DEC  TIME   HEX   TIME    DIFF"60 TIMER=0:FOR I=1 TO MX70 A=080 NEXT:TD=TIMER:GOSUB 92090 TIMER=0:FOR I=1 TO MX100 A=&H0110 NEXT:TH=TIMER:GOSUB 930120 TIMER=0:FOR I=1 TO MX130 A=1140 NEXT:TD=TIMER:GOSUB 920150 TIMER=0:FOR I=1 TO MX160 A=&H1170 NEXT:TH=TIMER:GOSUB 930180 TIMER=0:FOR I=1 TO MX190 A=2200 NEXT:TD=TIMER:GOSUB 920210 TIMER=0:FOR I=1 TO MX220 A=&H2230 NEXT:TH=TIMER:GOSUB 930240 TIMER=0:FOR I=1 TO MX250 A=3260 NEXT:TD=TIMER:GOSUB 920270 TIMER=0:FOR I=1 TO MX280 A=&H3290 NEXT:TH=TIMER:GOSUB 930300 TIMER=0:FOR I=1 TO MX310 A=4320 NEXT:TD=TIMER:GOSUB 920330 TIMER=0:FOR I=1 TO MX340 A=&H4350 NEXT:TH=TIMER:GOSUB 930360 TIMER=0:FOR I=1 TO MX370 A=5380 NEXT:TD=TIMER:GOSUB 920390 TIMER=0:FOR I=1 TO MX400 A=&H5410 NEXT:TH=TIMER:GOSUB 930420 TIMER=0:FOR I=1 TO MX430 A=6440 NEXT:TD=TIMER:GOSUB 920450 TIMER=0:FOR I=1 TO MX460 A=&H6470 NEXT:TH=TIMER:GOSUB 930480 TIMER=0:FOR I=1 TO MX490 A=7500 NEXT:TD=TIMER:GOSUB 920510 TIMER=0:FOR I=1 TO MX520 A=&H7530 NEXT:TH=TIMER:GOSUB 930540 TIMER=0:FOR I=1 TO MX550 A=8560 NEXT:TD=TIMER:GOSUB 920570 TIMER=0:FOR I=1 TO MX580 A=&H8590 NEXT:TH=TIMER:GOSUB 930600 TIMER=0:FOR I=1 TO MX610 A=9620 NEXT:TD=TIMER:GOSUB 920630 TIMER=0:FOR I=1 TO MX640 A=&H9650 NEXT:TH=TIMER:GOSUB 930660 TIMER=0:FOR I=1 TO MX670 A=10680 NEXT:TD=TIMER:GOSUB 920690 TIMER=0:FOR I=1 TO MX700 A=&HA710 NEXT:TH=TIMER:GOSUB 930720 TIMER=0:FOR I=1 TO MX730 A=11740 NEXT:TD=TIMER:GOSUB 920750 TIMER=0:FOR I=1 TO MX760 A=&HB770 NEXT:TH=TIMER:GOSUB 930780 GOTO 850790 TIMER=0:FOR I=1 TO MX800 A=12810 NEXT:TD=TIMER:GOSUB 920820 TIMER=0:FOR I=1 TO MX830 A=&HC840 NEXT:TH=TIMER:GOSUB 930850 TIMER=0:FOR I=1 TO MX860 A=.870 NEXT:TD=TIMER:PRINT "  . ";:PRINT USING"#####";TD;:PRINT"   ";880 TIMER=0:FOR I=1 TO MX890 A=&H0900 NEXT:TH=TIMER:GOSUB 930910 GOTO 910920 PRINT USING"### ##### ";A;TD;:PRINT"  ";:RETURN930 PRINT "&H";HEX\$(A);"  ";:PRINT USING"##### ";TH;:PRINT USING "###.##%";((TD-TH)/TD)*100:RETURN`

Running this program (eventually) displays:

So the answer is — for zero, 7% faster. For other single digit values, only slightly faster. For multiple digit values, about 30% faster. BUT, if using zero, using the period (“A=.”) will be about 16% faster than using HEX.

Thank you for coming to my talk.

Until next time…

This site uses Akismet to reduce spam. Learn how your comment data is processed.