[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Parsing numbers



    Date: Fri, 29 Sep 89 09:13:53 pdt
    From: hall@CTC.FMC.COM (David Hall)

    I was trying to read some numbers on a MacIvory (Genera 7.4) and
    noticed some peculiar behavior.  I got the same results on a 3640
    running 7.2.  (In the following examples the LET form was evaled,
    the number after ON was entered and the thing after the -> was
    returned.  (TYPE-OF *) yielded the thing after the ,)

The most error-free way to be sure of parsing strings into integers is with
PARSE-INTEGER rather than READ.

For example, (parse-integer "1111" :radix 2) -> 15
	     (parse-integer "1191" :radix 2) -> Error: Garbage character 9
						       seen while parsing
						       integer in "1191".
	     (parse-integer "123" :radix 16) -> 291
	     (parse-integer "1A3" :radix 16) -> 419

If you have to use READ (e.g., you're parsing floating-point or rational
numbers), use the variables SI:*READ-EXTENDED-IBASE-UNSIGNED-NUMBER* and
SI:*READ-EXTENDED-IBASE-SIGNED-NUMBER*.  Here is the documentation string for
the former:

  (documentation 'SI:*READ-EXTENDED-IBASE-UNSIGNED-NUMBER* 'variable) ->
"Controls how a token that could be a number or a symbol, and does not start
with a + or - sign, is interpreted when IBASE is greater than ten.
NIL => it is never a number.
T => it is always a number.
:SHARPSIGN => it is a symbol at top level, but a number after #X or #nR.
:SINGLE => it is a symbol except immediately after #X or #nR."

The default for these variables are :SINGLE and :SHARPSIGN, respectively,
which means that #X(+a small #xface in a -bad place) reads as
(10 SMALL 64206 IN A -2989 PLACE).

You can say 
  (let ((*read-base* 16)
	(si:*read-extended-ibase-unsigned-number* t)
	(si:*read-extended-ibase-signed-number* t))
    (read))
and if the next thing in the stream is (a small face in a bad place), the thing
which is returned is (10 SMALL 64206 IN 10 2989 PLACE).

About your second example:

    I guess this next example is OK in a perverse way, i.e. it would be
    correct if 9 were a binary digit with value 8 greater than 1.
     (let ((*read-base* 2)) (read))  on 1191  -> 31 , FIXNUM

I've always considered this behaviour to be a bug, but it's been that way
since Maclisp.  The Common Lisp manual doesn't say whether this is allowed,
forbidden, or neither.