## problem with integer

Q&A's, tips, howto's
Maurizio
Posts: 52
Joined: Mon Jul 28, 2003 3:06 pm
Location: Italy

### problem with integer

it seems that
(integer "12a")
it's a bug or a feature ?
(if it's a feature, how can i check for a valid integer ?)

Regards
Maurizio

Lutz
Posts: 5282
Joined: Thu Sep 26, 2002 4:45 pm
Contact:
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
Posts: 52
Joined: Mon Jul 28, 2003 3:06 pm
Location: Italy
well, but "12a", as well "12xyz" should not be considered an integer !
regards
Maurizio

HPW
Posts: 1377
Joined: Thu Sep 26, 2002 9:15 am
Location: Germany
Contact:
Then you must use:

Code: Select all

``````>(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
Posts: 5282
Joined: Thu Sep 26, 2002 4:45 pm
Contact:
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
Posts: 52
Joined: Mon Jul 28, 2003 3:06 pm
Location: Italy
My idea was to test a user-entered argument
to checkit was a proper number.
i've solved the problem with the following function

Code: Select all

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

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia
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
Posts: 5282
Joined: Thu Sep 26, 2002 4:45 pm
Contact:
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
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia
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 )
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
Posts: 5282
Joined: Thu Sep 26, 2002 4:45 pm
Contact:
thanks Nigel, 'integer' will now correctly cut to negative/positive -max and docs are changed.

Lutz

nigelbrown
Posts: 429
Joined: Tue Nov 11, 2003 2:11 am
Location: Brisbane, Australia
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

> (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

?unless the big number is infinity
Interestingly +INF converts to 0 with (integer ) viz

> (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
Posts: 5282
Joined: Thu Sep 26, 2002 4:45 pm
Contact:
>>
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