problem with integer

Started by Maurizio, December 06, 2003, 02:43:18 PM

Previous topic - Next topic

Maurizio

it seems that

  (integer "12a")

returns 12 instead of nil

it's a bug or a feature ?

(if it's a feature, how can i check for a valid integer ?)



Regards

Maurizio

Lutz

#1
This is a feature:



'integer' is translating from a string to a integer



'integer?' is checking if an integer



(integer? (integer "12a")) => true



newLISP uses the 'C" function strtoul() to convert .





Lutz

Maurizio

#2
well, but "12a", as well "12xyz" should not be considered an integer !

regards

Maurizio

HPW

#3
Then you must use:



>(eval-string "12")
12
>(integer? (eval-string "12"))
true
> (eval-string "12a")
nil


The feature of integer is that it try it best to make an integer of the string "12a". Then the 'a' ist cut off and the result is of course an integer.



This does work because a symbol can not start with a number.

So a symbol 12a could not exists.
Hans-Peter

Lutz

#4
There are some advantages to it, like:





(integer "077") => 63 ;; ocatl conversion



(integer "0x77) => 119 ;; hex conversion



(integer "100Kg") => 100 ;; stripping of units, currencies



Lutz

Maurizio

#5
My idea was to test a user-entered argument

to checkit was a proper number.

i've solved the problem with the following function

(define (number? x,temp)
  (set 'temp (integer x))
  (and temp
     (= x (format "%d" temp))))

Regards

Maurizio

nigelbrown

#6
Keep in mind that regrading leading + or spaces with number?

a leading + is not valid

eg

> (number? "+12")

nil

> (number? "-12")

true

>



I also noticed that the definition of what (integer ) will accept is not

quite the same as strtoul as strtoul will accept leading spaces while

(integer ) will not (that leading spaces are not allowed is stated in the manual)

viz

> (number? " 12")

nil

> (integer "     12")

nil



Borland says of strtol regarding leading whitespace (strtoul uses same rules) :

...the characters must match this generic format:



   [ws] [sn] [0] [x] [ddd]



where:



[ws]   =   optional whitespace

[sn]   =   optional sign (+ or -)

[0]   =   optional zero (0)

[x]   =   optional x or X



[ddd]   =   optional digits

...



Possibly for user input you may wish to accept leading spaces - but

perhaps you skip over this already.



Just a couple of points to bear in mind.

Nigel

Lutz

#7
in version 7.3.17 'integer' and 'float' will strip leading whitespace before doing the conversion:



(integer "  12") => 12

(float "  1.23") => 1.23

(integer " 0xff) => 255

(integer "  0755") => 493

(integer " abc") => nil

(integer " abc" 0) => 0

etc.



this way input strings from users don't need 'trim' before applying integer. When using the default value as second parameter with 0, then integer is equal compatible to strtoul()



Lutz

nigelbrown

#8
Further regarding integer conversion

Q:What should (integer ) be doing at the extremes?

I find:



> (integer "-2147483648")

-2147483648

> (integer "-2147483649")

2147483647

> -2147483649

-2147483648

>

That is, newlisp truncates it integers that are too negative (as is stated in the docs) while (integer ) wraps around to positive.

At  it says of strtoul at Linux Programmers manual ( http://unixhelp.ed.ac.uk/CGI/man-cgi?strtoul+3">http://unixhelp.ed.ac.uk/CGI/man-cgi?strtoul+3 )

RETURN VALUE

       The  strtoul()  function    returns either the result of the

       conversion or, if there was  a  leading   minus  sign,  the

       negation of the result of the conversion, unless the orig-

       inal (non-negated) value would  overflow;  in  the  latter

       case,  strtoul()    returns  ULONG_MAX  and  sets the global

       variable errno to ERANGE.

So the truncation to maximun seems correct behaviour rather than wrapping to positive. I don't have the Borland docs at this workstation to check their strtoul return info.







Also re (integer ) docs - they need to be corrected to be in line with changed behaviour:



The integer docs 7.3.17 still say "str must start with a number digit"

(integer "123")          => 123

(integer " 123")         => nil

while newlisp now does  



> (integer "   123")

123

>



Regards

Nigel

Lutz

#9
thanks Nigel, 'integer' will now correctly cut to negative/positive -max and docs are changed.



Lutz

nigelbrown

#10
Further on (integer ) - it chokes aka "crashes" on too big a floating point

when used in the second sense of its definition

integer

syntax: (integer str [default-exp] )

syntax: (integer num [default-exp] )

viz

newLISP v7.3.17 Copyright (c) 2003 Lutz Mueller. All rights reserved.



> (integer 3.5)

3

> (integer 1e8)

100000000

> (integer 1.5e8)

150000000

> (integer 1e20)





Probably relates to "math exception handling" thread

http://www.alh.net/newlisp/phpbb/viewtopic.php?t=102">http://www.alh.net/newlisp/phpbb/viewtopic.php?t=102



?unless the big number is infinity

Interestingly +INF converts to 0 with (integer ) viz



newLISP v7.3.17 Copyright (c) 2003 Lutz Mueller. All rights reserved.



> (float 3.5)

3.5

> (float 1e600)

+INF

> (setq infinity 1e600)

+INF

> (integer infinity)

0

> infinity

+INF

>



Apologies for stressing out newlisp with all these funny numbers.



Nigel

Lutz

#11
>>

Apologies for stressing out newlisp with all these funny numbers.

>>



No apologies! this is exactly what is needed to bring newLISP forward. Your involvement has brought newLISP a big step forward during the last weeks. Thankyou for investing the time to find out all this.



In the upcoming 7.4.0 rc1 (release candidate 1), all floats will be truncated to the min/max integers when using 'integer' in its second syntax when converting floats. NaNs will still return 0.



In the first syntax, when converting from string it will still behave like before (using strtol() for conversion, this gives us conversion of hex and octal too).



About the '(abs (sqrt -1))' crash on Win32 on the other thread.



Lutz