AutoCAD Lisp: Why does (rtos 8.6375 2 3) return 8.637 instead of 8.638 as expected?

<?xml encoding=”UTF-8″>By Philippe Leefsma

Q:

Why does (rtos 8.6375 2 3) return 8.637 instead of 8.638 as expected? How can I correct it?

A:

This is a known issue in AutoCAD and AutoLISP. However, it is more of a precision issue of computers than a bug of AutoCAD.

There is always a certain degree of inaccuracy when calculating values. This is the case in other programming languages as well. To demonstrate this, we will compare the numbers 8.6375 and 7.6375. Observe the following output in the AutoCAD command window:

Command: (rtos 7.6375 2 3)
“7.638”
Command: (rtos 7.6375 2 16)
“7.6375”
Command: (rtos 8.6375 2 3)
“8.637”
Command: (rtos 8.6375 2 16)
“8.637499999999999”

It may be surprising that the number 8.6375 is represented as 8.637499999999999 above.  The computer represents this value as a binary number (a series of 0s and 1s).  It must perform transformations or calculations for all other numbers (especially for decimals), thus causing the precision issue.

This is taken into account by the workaround below, which substitutes (bzh_rtos ) for the original (rtos ) function.  The comments help to explain the process:

<font color="#000000">(defun Bzh_rtos<br>   (num mod pre / A B len dec1 dec2 dec22 small_value real_num)<br>   (setq A (rtos num mod pre))  ;A contains the value (rtos) returns<br>   (setq B (rtos num mod (+ 1 pre))) <br>   (setq real_num num)</font><p></p><font>
</font><p><font color="#000000">   (setq len   (strlen A)  ;Length of A string<br>           dec1  (substr A len 1);The last decimal of A<br>           dec2  (substr B len 1);The next to the last decimal of B<br>           dec22 (substr B (+ len 1) 1);The last decimal of B<br>   )</font></p><font>
</font><p><font color="#000000">   ;;Set a fuzz factor. We can change it to other value as we like.<br>   (setq small_value (expt 0.1 (+ 1 14)))<br>   ;;Check if dec1 equals to dec2<br>   (if (= dec1 dec2)<br>      (if (= dec22 "5")<br>         (setq real_num (+ real_num small_value))<br>      )<br>   )</font></p><font>
</font><p><font color="#000000">   ;;Recaculate the adjusted number and return<br>   (rtos real_num mod pre)<br>)</font></p>

Comments

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading