[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
_numtostring
- To: berger@soe.berkeley.edu
- Subject: _numtostring
- From: wilcox@cmns.think.com
- Date: Fri, 14 Aug 92 09:28:05 EDT
- Cc: info-mcl@cambridge.apple.com
- In-reply-to: Daniel Berger's message of Thu, 13 Aug 92 11:32:58 PDT <9208131832.AA01924@dewey>
>I need to turn an integer into a string -
>
>Does anyone out there know how to make the trap _numtostring work?
>
>Format is too slow. Without _numtostring it looks like I will have to iterate
>over the digits of an integer and then push the individual chars into
> a vector.
>
>thanks
>Daniel
Hey, what timing! I just happened to have a similar need for speed yesterday.
You're right - format (and prin1-to-string) is much too slow on floats.
The following code is about 5 times faster. It uses #_NumToString via the
macro with-returned-pstrs. (I tried macro-expanding the code and hand-tuning it
since I knew that the number will always be 12 characters or less, but the
code actually got slower! Why...?) Note that this only works for numbers less
than 2^32; larger numbers are subjected to mod 2^32.
;; "magnitude of the integer is converted modulo 2^32"
;; -- Inside Macintosh I-490
;; so result will never be longer than 12 characters
Also note that the definition of the trap _numtostring in packages.lisp
has a spelling error: thenum should be the-num (or vice versa).
I have not tested this code extensively yet; there may be bugs. No warrantees
expressed, implied, impressed, replied, etc. Enjoy!
(deftrap _numtostring ((thenum :signed-long) (thestring (:pointer (:string 255))))
nil
(:no-trap (ccl::%gen-trap #xA9EE :d0 the-num :a0 thestring :word 0)))
^ should be thenum
(defun integer-to-string (number)
"Converts an integer to a string, using the toolbox."
(with-returned-pstrs ((string ""))
(#_numtostring number string)
(%get-string string)
))
(defun float-to-string (number fractional-digits)
"Converts a floating-point number to a string, ~
with a given number of digits following the decimal point."
(let* ((integral (floor number))
(int-string (integer-to-string integral)))
;; dont mess around with fractions if you dont have to
(if (zerop fractional-digits)
(concatenate 'string int-string ".")
(let* ((fractional (round (* (expt 10 fractional-digits)
(- number integral))))
(fract-string (integer-to-string fractional))
;; pad fraction with enough zeros to separate it from decimal
(pad-string (make-string (- fractional-digits (length fract-string))
:initial-element #\0)))
(concatenate 'string int-string "." pad-string fract-string)
))))