Author Topic: How lisp tell if a string is a number?  (Read 17711 times)

0 Members and 1 Guest are viewing this topic.

Daniel J. Ellis

  • Swamp Rat
  • Posts: 811
How lisp tell if a string is a number?
« on: March 24, 2009, 09:58:50 AM »
I'm working on updating a plot renumbering routine I wrote about a year ago.

We always put plot numbers on their own layer, so the routine originally worked by processing all of the objects on that layer.

This works OK, unless the plot number text isn't actually a number (for example, somone might want to note a binstore).

Is there a way to test whether the contents of a string are actually a number?

dJE
===
dJE

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How lisp tell if a string is a number?
« Reply #1 on: March 24, 2009, 10:04:09 AM »
Code: [Select]
(defun _DistOf ( x / result fixed )

[color=green]    ;;  Convert a string to a numerical value if possible. Also, if it
    ;;  can be determined that the intent of the string representation
    ;;  is that the number is to be an integer rather than an a real an
    ;;  integer is returned.
[/color]
    (vl-some
       '(lambda ( base ) (setq result (distof x base)))
       '(2 1 5 3 4)
    )

    (if result
        (if (vl-string-position 46 x)
            result [color=green]    ;; assume result is a real[/color]
            (if (eq result (setq fixed (fix result)))
                fixed  [color=green];; assume result is an integer[/color]
                result [color=green];; assume result is a real[/color]
            )
        )
    )
)

Code: [Select]
(if (setq dist (_DistOf (setq str "123.2")))
    (_DoStuffWithDist dist)
    (_DoStuffWithStr str)
)

Modify to suit. :)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: How lisp tell if a string is a number?
« Reply #2 on: March 24, 2009, 10:04:49 AM »
Hi,

(numberp (read str))
Speaking English as a French Frog

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How lisp tell if a string is a number?
« Reply #3 on: March 24, 2009, 10:14:57 AM »
Funny you should ask as this was just discussed on another forum.

Like Michael's, this will return a number or nil
Code: [Select]
(defun txt2num ( txt )
  (cond
    ((distof txt 5))
    ((distof txt 2))
    ((distof txt 1))
    ((distof txt 4))
    ((distof txt 3))
  )
)

This will test for a number within a string. (not what you want)
Code: [Select]
(vl-some '(lambda (x) (< 47 x 50)) (vl-string->list "your string 2"))
I like gile's test.
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How lisp tell if a string is a number?
« Reply #4 on: March 24, 2009, 10:19:41 AM »
I suppose we should ask for some typical data.

For example if the candidate values are always simple ints or floats (123 | 123.4) then the _DistOf function I provided is overkill, as (numberp (read "123")) -> T or (numberp (read "123.4")) -> T.

However, if the data may have fractions etc. that need to be properly interpreted as numerical values then (_DistOf "1-1/2\"") => 1.5 would be the route to go as (numberp (read "1-1/2\"")) would return nil.

PS: Nicely done Gile. :)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How lisp tell if a string is a number?
« Reply #5 on: March 24, 2009, 10:20:16 AM »
Funny you should ask as this was just discussed on another forum.

traitor :P
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How lisp tell if a string is a number?
« Reply #6 on: March 24, 2009, 10:35:48 AM »
I don't view our neighbors as enemies.
So don't blow my cover as a spy. 8-)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How lisp tell if a string is a number?
« Reply #7 on: March 24, 2009, 10:36:29 AM »
This also generates an error
(numberp (read ".5   "))  
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Re: How lisp tell if a string is a number?
« Reply #8 on: March 24, 2009, 10:38:58 AM »
I suppose we should ask for some typical data.
Yep, that would help. :)
TheSwamp.org  (serving the CAD community since 2003)

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Re: How lisp tell if a string is a number?
« Reply #9 on: March 24, 2009, 10:39:40 AM »
Code: [Select]
(numberp (read "11BN"))
nil
TheSwamp.org  (serving the CAD community since 2003)

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How lisp tell if a string is a number?
« Reply #10 on: March 24, 2009, 10:40:13 AM »
I don't view our neighbors as enemies.
So don't blow my cover as a spy. 8-)

forum slut

there, I said it

:lmao:
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How lisp tell if a string is a number?
« Reply #11 on: March 24, 2009, 10:41:13 AM »
Code: [Select]
(numberp (read "11BN")) => nil

But ... should "11BN" be interpreted as a number? I'm not thinking so. :)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How lisp tell if a string is a number?
« Reply #12 on: March 24, 2009, 10:45:54 AM »
Hey if you like sex what better than to sleep around. ;-)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How lisp tell if a string is a number?
« Reply #13 on: March 24, 2009, 10:49:09 AM »
If ya can't be good might as well be bad. :evil:
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Daniel J. Ellis

  • Swamp Rat
  • Posts: 811
Re: How lisp tell if a string is a number?
« Reply #14 on: March 24, 2009, 04:23:59 PM »
MP, I'm sorry, that's way beyond me.  Do all possible numbers need entering into the list-I can't believe that would be the case?  If so that would rule out its use here (it would leaving me needing to create a random? list up to 1000).  I can find evidence that VL-SOME is an autolisp function,  but nothing to suggest what it might do.  What do FIXED and RESULT need to be set to?  How do distof, x, and base get generated?  I assume one of them is the test string?

CAB, I assume your use of DISTOF is the one MP created?  Similarly or seem to need to process through all possible values?

Gile, this seems to be closest to what I want.  I assume that this will work on an non-number string without crashing?  Would I use it:
<code>
(IF
    (numberp (READ txt))
    (SETQ txt2 (ATOI txt))
)
</code>

Typical data are plot numbers on an housing estate, so values are always integers, starting from 1 up to about 600.  In terms of settings I'm going up to about 1000, purely because I can't imagine a situation where a greater value would be required/encountered.  I will go on to manipulate the number (comparison, addition or subtraction)  I just want to ensure the string is indeed a number to avoid errors and crashed.

dJE
===
dJE

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How lisp tell if a string is a number?
« Reply #15 on: March 24, 2009, 04:44:27 PM »
To solve your specific problem I would use this:
Code: [Select]
(if (and (setq num (distof str 2)) ; got a number else nil
          (setq num (fix num))      ; make an interger
          (< 0 num 1000)            ; range check
     )
   ;;  Do your plot using num var
)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

VovKa

  • Water Moccasin
  • Posts: 1631
  • Ukraine
Re: How lisp tell if a string is a number?
« Reply #16 on: March 24, 2009, 05:16:19 PM »
one more, nothing but digits allowed :)
Code: [Select]
(= str (itoa (atoi str)))

hermanm

  • Guest
Re: How lisp tell if a string is a number?
« Reply #17 on: March 24, 2009, 11:11:16 PM »
Code: [Select]
;;;----------------------str2num.lsp-------------------
;;;converts a string representing a number into a real or integer
;;;----------------------------------------------------
(defun str2num (str / chlst)
  (cond
    ((member (type str) '(INT REAL)) str);is a number, so return it
    ((= (type str) 'STR)
     (progn
       (setq chlst (vl-string->list str))
       (if (member nil
                   (mapcar
                     (function (lambda (x)
                                 (and (/= x 47)
                                      (> 58 x 44)
                                 )
                               )
                     )
                     chlst
                   )
           )
         nil ; the string does not represent a number
         (if (member 46 chlst) ;contains a decimal point
           (atof str) ;real
           (atoi str) ;integer
         );if
       );if
     );progn
    )
    ((= (type str) 'SYM) (str2num (eval str)));recurse on evaluated arg
    (T nil);not a number or a string which represents a number
  )
);str2num


MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How lisp tell if a string is a number?
« Reply #18 on: March 24, 2009, 11:48:30 PM »
MP, I'm sorry, that's way beyond me.

Sorry, trying to help, not confuse.

Do all possible numbers need entering into the list-I can't believe that would be the case?

No, I showed you how to use the function (which is supposed to make your life easier). Despite the fact that said function is overkill given the typical data being numbers as strings "starting from 1 up to about 600" as you put it, I'll try to explain for completeness' sake.

Let's say the string you wish to test is "123". If it can be converted to a number you want to use it in a calculation, say multiply it by 2, returning the result to the caller, otherwise you want to tell the user the string could not be coerced to a number and return nil to the caller.

Code: [Select]
(progn

    (setq str "123")

    (if (setq num (_DistOf str))
        (* 2 num)
        (progn (princ (strcat "String \"" str "\" cannot be coerced to a number.")) nil)
    )

)

==> 246

Now try it again but pass string "ABC".

Code: [Select]
(progn

    (setq str "ABC")

    (if (setq num (_DistOf str))
        (* 2 num)
        (progn (princ (strcat "String \"" str "\" cannot be coerced to a number.")) nil)
    )

)

==> String "ABC" cannot be coerced to a number.nil

Put one more way ... using your own example from later in the thread:

Instead of this:

Code: [Select]
(IF (numberp (READ txt))
    (SETQ txt2 (ATOI txt))
)

All you would have to do is this:

Code: [Select]
(if (setq num (_DistOf txt))
    (Do_Something_With_Num num)
)

PS: Using a variable named txt2 to represent a numerical value isn't advisable from a documentation perspective.

If so that would rule out its use here (it would leaving me needing to create a random? list up to 1000).

Sorry but you completely lost me.

I can find evidence that VL-SOME is an autolisp function,  but nothing to suggest what it might do.

It's in the AutoLISP Reference:

      Checks whether the predicate (the test) is not nil for (at least) one element combination.

In layman's terms it means the function will return true (and immediately stop processing) if one of the list items produces a non nil result when used in the test function, otherwise it will return nil.

What do FIXED and RESULT need to be set to?

"You" don't need to set them to anything, they are variables local to the _DistOf function, and are set / used by same.

How do distof, x, and base get generated?  I assume one of them is the test string?

Same as preceding comment.

HTH.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: How lisp tell if a string is a number?
« Reply #19 on: March 25, 2009, 02:52:41 AM »
I have, only one variant...

Code: [Select]
(wcmatch "your string 2" "*#*")

Daniel J. Ellis

  • Swamp Rat
  • Posts: 811
Re: How lisp tell if a string is a number?
« Reply #20 on: March 25, 2009, 03:28:08 AM »
MP, I'm sorry, that's way beyond me.

Sorry, trying to help, not confuse.

I get that, don't worry

Do all possible numbers need entering into the list-I can't believe that would be the case?

No, I showed you how to use the function (which is supposed to make your life easier). Despite the fact that said function is overkill given the typical data being numbers as strings "starting from 1 up to about 600" as you put it, I'll try to explain for completeness' sake.

Let's say the string you wish to test is "123". If it can be converted to a number you want to use it in a calculation, say multiply it by 2, returning the result to the caller, otherwise you want to tell the user the string could not be coerced to a number and return nil to the caller.

Code: [Select]
(progn

    (setq str "123")

    (if (setq num (_DistOf str))
        (* 2 num)
        (progn (princ (strcat "String \"" str "\" cannot be coerced to a number.")) nil)
    )

)

==> 246

Now try it again but pass string "ABC".

Code: [Select]
(progn

    (setq str "ABC")

    (if (setq num (_DistOf str))
        (* 2 num)
        (progn (princ (strcat "String \"" str "\" cannot be coerced to a number.")) nil)
    )

)

==> String "ABC" cannot be coerced to a number.nil

Put one more way ... using your own example from later in the thread:

This seems to be using the _distof function you originally posted?  It's *that* that I need explaining.  I understand that you need to run the test, then do something with the result, it's how the test is working that I don't understand.  Sorry

Instead of this:

Code: [Select]
(IF (numberp (READ txt))
    (SETQ txt2 (ATOI txt))
)

So this will work?


All you would have to do is this:

Code: [Select]
(if (setq num (_DistOf txt))
    (Do_Something_With_Num num)
)
Except that, unless I've really gotten the wrong end of the stick, that's not all you need to do.  You need the mysterious _Distof function first.


PS: Using a variable named txt2 to represent a numerical value isn't advisable from a documentation perspective.

Very true, that's one of the things that's changing as I rework the routine.

I can find evidence that VL-SOME is an autolisp function,  but nothing to suggest what it might do.

It's in the AutoLISP Reference:

      Checks whether the predicate (the test) is not nil for (at least) one element combination.

In layman's terms it means the function will return true (and immediately stop processing) if one of the list items produces a non nil result when used in the test function, otherwise it will return nil.
I must admit I tend to avoid the AutoLISP reference, it tends to say things like that that don't say what the function's supposed to do.  Can it be used on a non-list?

What do FIXED and RESULT need to be set to?

"You" don't need to set them to anything, they are variables local to the _DistOf function, and are set / used by same.

How do distof, x, and base get generated?  I assume one of them is the test string?

Same as preceding comment.

HTH.

So just trust the magic ^_^

Sorry if that sounds overly negative, but I instictively don't like using stuff that just pop in and out of existence without my understanding them.


I know you're trying to help, so thankyou.

dJE
===
dJE

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: How lisp tell if a string is a number?
« Reply #21 on: March 25, 2009, 05:32:26 AM »
What is the number kept as a string?
"1e-3" - number?
"pi" - number?
" 1" - number?
"1 " - number?
" 1 " - number?
".1" - number?
"1." - number?
"1.1" - number?
"a1" - number?
"1a" - number?
"a1a" - number?
"1a1" - number?
"(1+ 2)" - number?


MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How lisp tell if a string is a number?
« Reply #22 on: March 25, 2009, 07:26:00 AM »
I must admit I tend to avoid the AutoLISP reference ...

And thus ends my participation.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: How lisp tell if a string is a number?
« Reply #23 on: March 25, 2009, 07:43:59 AM »
What is the number kept as a string?
"1e-3" - number?
"pi" - number?
" 1" - number?
"1 " - number?
" 1 " - number?
".1" - number?
"1." - number?
"1.1" - number?
"a1" - number?
"1a" - number?
"a1a" - number?
"1a1" - number?
"(1+ 2)" - number?

Using evaluate from this thread ...

Code: [Select]
(defun evaluate ( expression / result )
    (setq result
        (vl-catch-all-apply
           '(lambda ( )
                (eval
                    (if (eq 'str (type expression))
                        (read expression)
                        expression
                    )
                )
            )
        )
    )   
    result
)

Code: [Select]
(setq candidates
    '(
        "1e-3"   
        "pi"     
        " 1"     
        "1 "     
        " 1 "   
        ".1"     
        "1."     
        "1.1"   
        "a1"     
        "1a"     
        "a1a"   
        "1a1"   
        "(1+ 2)"
    )   
)

Code: [Select]
(foreach candidate candidates
    (princ (setq text (vl-string-trim " " candidate)))
    (princ (substr "       " 1 (- 6 (strlen text))))
    (princ " ... ")
    (princ (evaluate candidate))
    (princ "\n")
    (princ)
)

Result
Code: [Select]
1e-3   ... 0.001
pi     ... 3.14159
1      ... 1
1      ... 1
1      ... 1
.1     ... #<%catch-all-apply-error%>
1.     ... 1.0
1.1    ... 1.1
a1     ... nil
1a     ... nil
a1a    ... nil
1a1    ... nil
(1+ 2) ... 3

With very little effort it could be made far more robust, but alas my interest in this thread wanes.

Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: How lisp tell if a string is a number?
« Reply #24 on: March 25, 2009, 08:11:29 AM »
(atoi ".1");=>> 0
(atof ".1");=>> 0.1

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: How lisp tell if a string is a number?
« Reply #25 on: March 25, 2009, 08:14:06 AM »
(atoi ".");=>> 0
(atof ".");=>> 0.0