A fellow Hitchhiker’s Guide To The Galaxy fan pointed out to me some years ago that 6 times 9 is 42 in base 13.
OK. Here are a couple of vanilla hex-to-number and number-to-hex handlers that can cope with negatives, using the “signed number” convention. The hex-to-number one appeared the other day in this thread in the OS X forum. The parameters are the hexadecimal string to be converted and a boolean that signifies whether or not the number’s to be regarded as “signed”.
on hexToNum from h given sign:sign
script o
property hexChrs : "0123456789abcdef" as Unicode text -- TIDs obey AppleScript's case attribute with Unicode.
on getHexVal(c)
set AppleScript's text item delimiters to c
set v to (count text item 1 of hexChrs)
if (v is 16) then error "Non-hex character(s)."
return v
end getHexVal
end script
set astid to AppleScript's text item delimiters
try
set h to h as Unicode text -- Speeds up use of TIDs with Unicode 'hexChrs' in o.
tell o to set n to getHexVal(character 1 of h)
if (sign) and (n > 7) then set n to n - 16
repeat with i from 2 to (count h)
tell o to set n to n * 16 + getHexVal(character i of h)
end repeat
on error msg number errNum
set AppleScript's text item delimiters to astid
error "hexToNum handler: " & msg number errNum
end try
set AppleScript's text item delimiters to astid
return n
end hexToNum
hexToNum from "FFFE" without sign -- Treat "FFFE" as an unsigned number.
--> 65534
hexToNum from "FFFE" with sign -- Treat "FFFE" as a signed number.
--> -2
The number-to-hex handler is new today. Its parameters are the number to be hexadecimalised and the required “resolution” (for want of a better word). It produces as many hex digits as are required to express the number and, if necessary, adds leading "0"s or "F"s to pad out the number of digits to the nearest multiple of the “resolution”.
on numToHex(n, res)
-- Round the input value to the nearest whole-number. (Just in case it's fractional.)
set n to n div 0.5 - n div 1
script o
property hexDigits : missing value
property hexOut : {}
end script
if (n > -1) then
-- The number's positive.
set o's hexDigits to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}
-- Construct a list of the hexadecimal digits, working backwards from the lowest-order one.
set widthNow to 0
repeat
set beginning of o's hexOut to item (n mod 16 + 1) of o's hexDigits
set n to n div 16
set widthNow to widthNow + 1
-- Finish when n is exhausted and the digit count is a multiple of the resolution.
if (n is 0) and (widthNow mod res is 0) then exit repeat
end repeat
else
-- The number's negative.
set o's hexDigits to {"1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "0"}
set negatives to "89ABCDEF"
-- Construct a list of the hexadecimal digits, working backwards from the lowest-order one.
set widthNow to 0
repeat
set c to item (n mod 16 - 1) of o's hexDigits
set beginning of o's hexOut to c
set n to (n + 1) div 16 - 1
set widthNow to widthNow + 1
-- Finish when n is exhausted, the digit count is a multiple of the resolution,
-- and the first digit in the list expresses the negative sign bit.
if (n is -1) and (widthNow mod res is 0) and (c is in negatives) then exit repeat
end repeat
end if
-- Coerce the digit list to string.
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ""
set hexOut to o's hexOut as string
set AppleScript's text item delimiters to astid
return hexOut
end numToHex
numToHex(-255, 1) -- Return only the necessary digits.
--> "F01"
numToHex(-255, 2) -- Pad the number of digits to the nearest multiple of 2.
--> "FF01"
numToHex(1.23456789E+9, 16)
--> "00000000499602D2"
As a pair of complimentary handlers, they should ideally both have either labelled or ordered parameters; but individually, I think they make more sense as they are.
Edit: corrected a sloppy assertion in one of the first script’s comments that TIDs are case-insensitive with Unicode. In fact, they follow the current setting of AppleScript’s ‘case’ attribute. This is ‘ignoring case’ by default, but can of course be changed to ‘considering case’ “ in which case AppleScript’s TIDs will be case-sensitive with Unicode too. With strings, they’re case-sensitive anyway, regardless of the attribute setting.