DVDM 发表于 2022-7-6 12:44:57

What's rounding down my v

Hi folks,
 
I have an odd issue with an old lisp routine. We’ve been using this routine from the year 0, and somehow an error snuck in so it doesn’t work as it should. I know for a fact it once used to work as it should, I never touched it or modified it, and now something goes wrong somewhere.
It’s a routine that sets a few parameters, and will then draw a spring with a particular diameter. The wire diameter should be 27mm (radius 13.5mm), but for some reason, the end result is a spring with a diameter 26mm. Something is causing that number to be rounded down to 26mm (=radius 13mm).
 
Now, where it gets really weird is this: say if I enter Diameter 29mm, it rounds down to 28mm. Ok, sounds like that can be expected. However, if I go in and say Diameter 27.0001mm, it will go and draw me a circle with a diameter 27.0001mm. No rounding up or down this time. I can cheat the system by telling it to draw a circle with diameter 27.00000000001mm, and it will give me exactly what I want.
 
Am I dealing with a bug here, or can someone tell from looking at the code that the problem is in there? I'd be curious if others can reproduce this same problem. I'm running Acad 2010, and unfortunately i cannot test it on a previous version myself, because I suspect it's not the code, but Acad 2010 causing it.

Thanks
 

(defun C:D27 (/ d3 d2 n) (setq d3 162) (setq d2 27) (setq n 7) (spg))(defun SPG (/ a ang d1 h p pt p1 p2 p3 p4 p5 p6 p7 p8 p9) (setq osm (getvar "OSMODE")) (setvar "CMDECHO" 0) (setq oer *error**error* seterr ) (setq d1 (- d3 d2)) (setq pt (getpoint "\nSelect start point: ")h(getdist pt "\nSpring height: ") )(setvar "OSMODE" 0) (setq ang (getangle pt "\nAt base angle : ")) (if (not ang)   (setq ang (/ pi 2))   (setq ang (+ ang (/ pi 2))) ) (setq   a (atan (/ d2 2)    (sqrt      (- (* (- (* 0.75 d1) (/ d2 2)) (- (* 0.75 d1) (/ d2 2)))(* 0.25 d2 d2)      )    )   ) ) (setq p1 (polar pt (+ ang (/ pi 2)) (/ d1 4))p2 (polar pt (- ang (/ pi 2)) (/ d1 2))p3 (polar p2 (+ ang (/ pi 2)) (/ d2 2))p4 (polar p2 (- ang (/ pi 2)) (/ d2 2))p5 (polar p2 (+ ang a) (/ d2 2)) ) (command ".LINE" p1 p3 "") (setq p7 (ssadd (entlast))) (command ".LINE" p3 p4 "") (ssadd (entlast) p7) (command ".LINE" p5 p1 "") (ssadd (entlast) p7) (command ".ARC" p3 p5 p4) (ssadd (entlast) p7) (setq p(/ (- (* 2 h) (* d2 2)) (- (* 2 n) 1))p9 (/ (+ p d2) 2)p1 (polar p2 ang p9)p2 (polar pt (+ ang (/ pi 2)) (/ d1 2))p2 (polar p2 ang (/ d2 2))a(atan (- p9 (/ d2 2)) d1)p3 (polar p1 (+ ang pi a) (/ d2 2))p4 (polar p1 (+ ang a) (/ d2 2))p5 (polar p2 (+ ang pi a) (/ d2 2))p6 (polar p2 (+ ang a) (/ d2 2)) ) (command ".LINE" p5 p3 "") (ssadd (entlast) p7) (command ".LINE" p6 p4 "") (ssadd (entlast) p7) (command ".CIRCLE" p1 (/ d2 2)) (ssadd (entlast) p7) (command ".CIRCLE" p2 (/ d2 2)) (ssadd (entlast) p7) (command ".COPY"   p7   ""   pt   pt   ".MOVE"   p7   ""   pt   (polar pt ang h)   ".ROTATE"   p7   ""   (polar pt ang h)   "180" ) (if (> n 2)   (progn   (setq p1 (polar p1 ang p)    p2 (polar p2 ang p)    a(atan (/ p 2) d1)    p3 (polar p1 (+ ang pi a) (/ d2 2))    p4 (polar p1 (+ ang a) (/ d2 2))    p5 (polar p2 (+ ang pi a) (/ d2 2))    p6 (polar p2 (+ ang a) (/ d2 2))   )   (command ".LINE" p5 p3 "")   (setq p7 (ssadd (entlast)))   (command ".LINE" p6 p4 "")   (ssadd (entlast) p7)   (command ".CIRCLE" p1 (/ d2 2))   (ssadd (entlast) p7)   (command ".CIRCLE" p2 (/ d2 2))   (ssadd (entlast) p7)   ) ) (if (> n 3)   (progn (setq p8 0)   (repeat (- n 3)   (setq p8 (+ 1 p8))   (command ".COPY" p7 "" pt (polar pt ang (* p8 p)))   )   ) ) (redraw) (setq *error* oer) (setvar "OSMODE" osm) (princ))

gile 发表于 2022-7-6 13:37:45

Hi,
 
I'ts not a bug, it's not due to 2010 behavior and I can't believe it worked fine one time.
This is due to the division (/) lISP operator implementation which never changed.
With LISP arithmetic operators (+,-,*,/, rem, expt) if all arguments ar integers, the result will be an integer too. If almost one argument is a real number the result will be a real number.
 
For example:
(/ 27 2) returns 13
(/ 27.02) returns 13.5
 
So just replace integers by reals in the c:d27 routine so that the wire diameter will be 27.0 and the spring diameter 162.0 (instead of 160):
 

(defun C:D27 (/ d3 d2 n) (setq d3 162.0) (setq d2 27.0) (setq n 7) (spg))

DVDM 发表于 2022-7-6 14:10:21

You are right, someone must have changed it somewhere along the line then. It just took quite some time for someone here to notice! Luckily it's a little used feature, rather than a lot of incorrect springs generated in many drawings.
 
Thanks for your help gile, much appreciatedI never would have figured this out. I thought a number had to be defined as an integer for it to behave as one.
页: [1]
查看完整版本: What's rounding down my v