Question

I want to turn a large number, actually the present time in seconds counted from the unix epoch time, into a hexatridecimal string.

I hacked some code a long time ago, which (I think) worked on an earlier version of emacs, but it does not work any more on emacs 23 that I use now (It might be possible that I messed up the code).

The difficulty at the time I wrote it was that the number was large to be handled as one argument for certain functions, so I had to divide it, do something, and put them together. For example, if you give a large number to string-to-number, it gives back a float even though I want an integer.

Can anyone suggest a rewrite of it?

Following is the broken code that I wrote. It does not work, but may give you an idea of what I am trying to do. First, these are all subroutines that are used below:

(defun seconds-since-origin ()
    (string-to-number (concat
        (number-to-string (- (string-to-number
            (substring (format-time-string "%s") 0 5)
         ) 10000))
    (substring (format-time-string "%s") 5)
)))

(defun hexatridecimal (decimal)
(concat
    (let ((quotient (/ decimal 36)))    (if (> quotient 35)
        (hexatridecimal quotient)
        (hexatridecimal-digit quotient)
    ))
    (hexatridecimal-digit (% decimal 36))
))

(defun hexatridecimal-digit (number)
    (nth number (list
"0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
    "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"))
)

The following will be the main function that will be called:

(hexatridecimal (seconds-since-origin))
Was it helpful?

Solution

Using a 64-bit Emacs (which can handle integers like you're using), make the following changes:

(defun seconds-since-origin ()
  (string-to-number (format-time-string "%s")))

(defun hexatridecimal (decimal)
  (let ((quotient (/ decimal 36))
        (remainder (% decimal 36)))
    (concat 
     (if (> quotient 0)
         (hexatridecimal quotient)
       "")
     (hexatridecimal-digit remainder))))

Note: this does assume a 64-bit Emacs which has more bits for large integers than the 32-bit builds.

If you want to work on a 32-bit Emacs, you can use calc's big-int capability to do the maths for you, and adjust the code appropriately.

Edited to add: Here's the version using calc's bignum capabilities:

(require 'calc)
(require 'calc-ext)
(defun seconds-since-origin ()
  (math-read-number-simple (format-time-string "%s")))
(defun hexatridecimal (decimal-bignum)
  (let* ((q-r (math-idivmod decimal-bignum 36))
     (quotient (car q-r))
     (remainder (cdr q-r)))
(concat 
 (if (math-lessp 0 quotient)
     (hexatridecimal quotient)
   "")
 (hexatridecimal-digit remainder))))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top