Exchange Forum > AutoLISP and Visual LISP
Strings to Numbers
Page 1 of 2
1 2
Strings to Numbers

#1

Rasmussen
Join Date:
12-10-2007
Is there a reliable way to determine if a string is an integer or a real number. The AutoLISP functions atoi and atof don't always return the true values. Here's a few examples of what I'm referring to.
Code:
(atoi "3/1")   = 3
(atof "3/1")   = 3.0
(distof "3/1") = 3.0
(atoi "3/8")   = 3    incorrect
(atof "3/8")   = 3.0  incorrect
(distof "3/8") = 0.375
(atoi "3.8")   = 3    incorrect
(atof "3.8")   = 3.8
(distof "3.8") = 3.8
Strings to Numbers

#2

Cricket
Join Date:
08-30-2007
I would think the distof function is more reliable. It has a mode parameter that may affect the result. The mode signifies the units in which the string is currently formatted. It corresponds to the values allowed for the Lunits system variable.
1 Scientific, 2 Decimal, 3 Engineering, 4 Architectural, 5 Fractional
Strings to Numbers

#3

gile
Join Date:
11-06-2007
Hi Rasmussen,
 
I don't agree with you, all the returns are correct regarding these functions are "converting" functions not mathematic equalities.
 
atoi converts to an integer even if the argument doesn't describes an integer as well, (fix 3.8) returns 3, and this doesn't means 3.8 equals 3.
 
You have to do your conversions (choose the function you need) regarding to what type of data is expected and what type of conversion you need in your program.
 
You can also use the c:cal function (have to load it if it's not) iwhich is a calculator rather than a convertor.
 
Code:
;; loading geomcal.arx
(or (member "geomcal.arx" (arx)) (arxload "geomcal"))
 
(c:cal "3") returns 3
(c:cal "3.0") returns 3.0
(c:cal "3.") returns 3.0
(c:cal ".3" returns 0.3
(c:cal "3.8") returns 3.8
(c:cal "3/8") returns 0.375
(c:cal "3+8") returns 11
(c:cal "3-1.0") returns 2.0
(c:cal "3*8") returns 24
Strings to Numbers

#4

Rasmussen
Join Date:
12-10-2007
Gile, I didn’t know that you can use the c:cal in that format. I’m considering using a function to verify if the user has entered a valid integer in a dialog edit box. Other times I just need to verify if the value is a valid real number.
 
Thanks for your help.
Strings to Numbers

#5

Quick Silver
Join Date:
11-01-2007
Why not just compare atoi and atof with the distof function using the decimal mode 2?
 
Code:
(defun checkreal (text)
 (if (= (atof text)(distof text 2))
  (atof text)
 )
)
(defun checkinteger (text)
 (if (= (atoi text)(distof text 2))
  (atoi text)
 )
)
Strings to Numbers

#6

gile
Join Date:
11-06-2007
If you want to check if a string describes an integer you can use the type an read function (care with read: if the string begins with a dot an error will occur)
 
Code:
(defun isint (str)
  (and (not (= "." (substr str 1 1)))
       (= (type (read str)) 'INT)
  )
)
Strings to Numbers

#7

Zeanor
Join Date:
07-26-2007
I like Giles suggested method with type and real. It also seems to work with reals in most cases.
I was working on a longer version that verifies if the string lengths match up. It may not be as efficient but here it is.
 
Code:
(defun IntNum (Text / Count Len Number Valid)
  (if (= (atoi Text)(atof Text))
    (progn
      (setq Number (atoi Text) Count 1 Len 0)
      (while (> (fix (/ (abs Number) Count)) 0)
        (setq Len (1+ Len))
        (setq Count (* Count 10))
      )
      (if (< Number 1)
        (setq Len (1+ Len))
      )
      (if (= (strlen Text) Len)
        (setq Valid t)
      )
    )
  )
  Valid
)
 
(defun RealNum (Text / Count Len Number Valid)
  (if (= (substr Text 1 1) ".")
    (setq Text (strcat "0" Text))
  )
  (if (= (substr Text 1 2) "-.")
    (setq Text (strcat "-0." (substr Text 3)))
  )
  (setq Len 0)
  (if (= (atof Text)(atoi Text))
    (cond
      ((not (vl-string-search "." Text))
        (setq Text (strcat Text ".0") Len (1+ Len))
      )
      ((= (substr Text (strlen Text)) ".")
        (setq Text (strcat Text "0") Len (1+ Len))
      )
      ((setq Len (1+ Len)))
    )
  )
  (setq Number (atof Text))
  (if (and (< Number 0)(= Len 0))
    (setq Len (1+ Len))
  )
  (if (< Number 1)
    (setq Len (1+ Len))
  )
  (while (/= (fix (abs Number)) 0)
    (setq Len (1+ Len))
    (setq Number (* Number 0.1))
  )
  (if (setq Count (vl-string-search "." Text))
    (progn
      (setq Number (atof (substr Text (+ Count 2))))
      (setq Len (1+ Len))
      (while (/= (fix (abs Number)) 0)
        (setq Len (1+ Len))
        (setq Number (* Number 0.1))
      )
    )
  )
  (if (= (strlen Text) Len)
    (setq Valid t)
  )
  Valid
)
Strings to Numbers

#8

Bennett
Join Date:
07-26-2007
This function fixes the string before it gets to the (type (read str)) line.
 
Code:
(defun isreal (str)
 (if (= (substr str 1 1) ".")
  (setq str (strcat "0" str))
 )
 (if (= (substr str 1 2) "-.")
  (setq str (strcat "-0." (substr str 3)))
 )
 (or (= (type (read str)) 'REAL)(= (type (read str)) 'INT))
)
 
I revised the function to also accept integers as being valid.
Strings to Numbers

#9

Rasmussen
Join Date:
12-10-2007
The isint and isreal functions work great.
Thanks for all your help.
Strings to Numbers

#10

Arch_Eric
Join Date:
04-02-2008
Couldn't you do this:
 
Code:
(defun isint(a) (if (= (type (c:cal a)) 'INT) T nil))
(defun isreal(a) (if (= (type (c:cal a)) 'REAL) T nil))
Page 1 of 2
1 2