Author Topic: atof with read-line function  (Read 2766 times)

0 Members and 1 Guest are viewing this topic.

Coder

  • Swamp Rat
  • Posts: 827
atof with read-line function
« on: October 06, 2011, 06:21:22 PM »
Hello .

I am trying to read data from a .txt file and the data are coordinates and when I use function atof it would not
convert the number to the correct decimal numbers which is for example .

Code: [Select]
(setq str1 (read-line Myfile)) ;; "1234.56789"
(setq x (atof str1)) ;; -> the conversion would be 1234.0

Is there any way to get the same number as it was string to real number without loosing full decimal numbers of it ?

Many thanks

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: atof with read-line function
« Reply #1 on: October 06, 2011, 06:23:26 PM »

(read "1234.56789")
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Coder

  • Swamp Rat
  • Posts: 827
Re: atof with read-line function
« Reply #2 on: October 06, 2011, 06:27:46 PM »
Thanks .

That's the same like atof , but if you try to convert the variable instead of the number , it would not give the correct decimals.

Jeff_M

  • King Gator
  • Posts: 4099
  • C3D user & customizer
Re: atof with read-line function
« Reply #3 on: October 06, 2011, 06:31:22 PM »
Check your variable, coder. (rtos x 2 5) I'd be willing to bet it will return the same number you read from the file.

kraz

  • Guest
Re: atof with read-line function
« Reply #4 on: October 06, 2011, 08:36:45 PM »
(rtos (atof str1) 2 6) <= variable had remember original real number but autocad doesn't display full real number
maybe, some autocad system variable control the display decimal places.

efernal

  • Bull Frog
  • Posts: 206
Re: atof with read-line function
« Reply #5 on: October 06, 2011, 09:19:05 PM »
check your source file....

Command: (atof "121212.5555")
121213.0
Command: (atof "121212,5555")
121212.0
e.fernal

efernal

  • Bull Frog
  • Posts: 206
Re: atof with read-line function
« Reply #6 on: October 06, 2011, 09:22:27 PM »
see above...
Command: (atof "12.55555")
12.5556

Command: (atof "1212.5555")
1212.56

Command: (atof "121212.55555")
121213.0

Command: (setq teste (atof "121212.5555"))
121213.0

Command: (princ (rtos teste 2 6))
121212.5555

"121212.5555"
e.fernal

Coder

  • Swamp Rat
  • Posts: 827
Re: atof with read-line function
« Reply #7 on: October 07, 2011, 02:23:03 AM »
Thank you all for your efforts .

I want to convert the strings that have been taken from the .txt file to real to be used as coordinates , and atof ignores the decimal numbers which
would not be accurate for the location of the later entmake entities .

Is there any other function that can convert strings to real instead of the atof ?

Many thanks

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: atof with read-line function
« Reply #8 on: October 07, 2011, 02:44:32 AM »
... and atof ignores the decimal numbers which
would not be accurate for the location of the later entmake entities ...
No it "doesn't" ignore the decimal fraction. It just doesn't "display" it by default. As shown already by efernal if you simply princ the value obtained from atof then it might "appear" as if the decimals have been cropped off, but if you force it to display all the decimals through using rtos then you see that they're actually there!

So no, using the value you got from read or atof would be perfectly accurate. It's the other way round when you start loosing accuracy: using princ, prin1, print, write-line and/or rtos may crop decimals off the number.

Actually when I save reals into a text file, I tend to encode them - usually using Base64 encoding. E.g.
Code: [Select]
;|---------------------------------------------------------------------------------------
= Base64toR =
Converts a base64 string starting with %%64| into a real value.  The dot (.) used as the
scientific notation's exponent split.

=== Arguments ===
str : The string to convert

=== Result ===
A real value converted from the string.
---------------------------------------------------------------------------------------|;
(defun Base64toR (str / digits c m val e)
  (setq digits (vl-string->list "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
        str    (vl-remove-if-not
                 '(lambda (c) (vl-position c digits))
                 (reverse (cdr (reverse (vl-string->list (substr (vl-string-trim "%64" str) 2)))))
               )
        val    0.0
        m      (= (car str) 45)
        str    (cdr str)
  )
  (while (/= (setq c (car str)) 46)
    (setq val (+ (* val 64.0) (* (vl-position c digits) 1.0)))
    (setq str (cdr str))
  )
  (if m
    (setq val (* val -1.0))
  )
  (setq str (cdr str)
        m   (= (car str) 45)
        str (cdr str)
        e   0
  )
  (while str
    (setq e   (+ (* e 64) (vl-position (car str) digits))
          str (cdr str)
    )
  )
  (if m
    (setq e (* e -1))
  )
  (* val (expt 64.0 e))
)

 ;|---------------------------------------------------------------------------------------
= RtoBase64 =
Converts an integer / real into a base64 string.

=== Arguments ===
val : The integer / real value to convert

=== Result ===
A string starting with %%64| and continuing with a scientific notation in base64 with .
as the exponent split.
---------------------------------------------------------------------------------------|;
(defun RtoBase64 (val / str e i digits)
  (setq str    (strcat "%%64|"
                       (if (minusp val)
                         "-"
                         "+"
                       )
               )
        val    (abs (* val 1.0))
        e      0
        digits "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  )
  (while (< val 1.0)
    (setq val (* val 64.0)
          e   (1- e)
    )
  )
  (while (> val 1.0)
    (setq val (/ val 64.0)
          e   (1+ e)
    )
  )
  (while (/= val 0.0)
    (while (< val 1.0)
      (setq val (* val 64.0)
            e   (1- e)
      )
    )
    (while (>= val 64.0)
      (setq val (/ val 64.0)
            e   (1+ e)
      )
    )
    (setq i   (fix val)
          str (strcat str (substr digits (1+ i) 1))
          val (- val (* i 1.0))
    )
  )
  (setq str (strcat str
                    "."
                    (if (minusp e)
                      "-"
                      "+"
                    )
            )
        e   (abs e)
  )
  (if (= e 0)
    (setq str (strcat str "0"))
    (while (> e 0)
      (setq str (strcat str (substr digits (1+ (rem e 64)) 1))
            e   (/ e 64)
      )
    )
  )
  (strcat str "|64%%")
)
That way it keeps the exact accuracy in both directions (read & write).
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.