... 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.
;|---------------------------------------------------------------------------------------
= 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).