Hi All,
I am trying to write a lisp program to get the area of a polyline to 4 significant figures, if it is greater than 10000, instead of a set number of decimal places.
eg 103948 => 103900, 123.456 => 123.5, 1.07345 => 1.073
any ideas on how I can do this?
Currently after getting the area of the polyline I use:
(if (< lotarea 10000);Check if ha or m^2 label required (setq lotarea (strcat (itoa (fix lotarea)) " m\u+00B2")) (setq lotarea (strcat (rtos (/ lotarea 10000) 2) " ha")) )
This gives me area current system precision, just not sure of how to tackle this.
Thanks in Advance
Steve 🙂
Solved! Go to Solution.
Solved by Lee_Mac. Go to Solution.
Solved by Kent1Cooper. Go to Solution.
Try the following function Steve:
(defun rtosigfig ( n f / d ) (LM:num->str (* (atof (rtos (/ n (setq d (expt 10.0 (- (fix (/ (log n) (log 10.0))) f -1)))) 2 0)) d)) ) ;; Number to String - Lee Mac ;; Converts a supplied numerical argument to a string (defun LM:num->str ( x / dim rtn ) (if (equal x (atof (rtos x 2 0)) 1e-8) (rtos x 2 0) (progn (setq dim (getvar 'dimzin)) (setvar 'dimzin 8) (setq rtn (vl-catch-all-apply 'rtos (list x 2 15))) (setvar 'dimzin dim) (if (not (vl-catch-all-error-p rtn)) rtn) ) ) )
Call the above with the number to be rounded and the number of significant figures to round to, e.g.:
_$ (rtosigfig 103948 4) "103900" _$ (rtosigfig 123.456 4) "123.5" _$ (rtosigfig 1.07345 4) "1.073"
Unfortunately, I find some things don't come out right with the (rtosigifig) function. Admittedly some of them would never be applicable to the OP's lot areas situation, but since they list other examples that also wouldn't be, and as a general application, it ought to work according to all the rules for significant figures, and be applicable to all types of numbers.
Command: (rtosigfig 234 5)
"234"
[only 3 sig-figs; trailing 0's are significant -- should be "234.00"]
Command: (rtosigfig 0.12343556 4)
"0.123"
[only 3 sig-figs; leading 0's are not significant -- should be "0.1234" -- likewise for any number between -1 and 1 (other than 0 -- see below)]
Command: (rtosigfig -12.3456 4)
; error: function undefined for argument: -12.3456
[likewise for any negative number]
And not that one would very likely ever want to express 0 with significant figures, but:
Command: (rtosigfig 0 4)
; error: function undefined for argument: 0
Whereas with the (sigfig) function below:
Command: (sigfig 234 5)
"234.00"
Command: (sigfig 0.12343556 4)
"0.1234"
Command: (sigfig -12.3456 4)
"-12.35"
Command: (sigfig 0 4)
"0.0000"
;; SigFig.lsp
;; To express a specified number, real or integer ['num' argument] in a
;; text string to a specified number of significant figures ['sf' argument].
;; Kent Cooper, 7 November 2014
(defun sigfig (num sf / dimz whole fixfigs adj sigfigged sci ex)
(setq dimz (getvar 'dimzin))
(if (> dimz 3) (setvar 'dimzin 0)); leading/trailing 0's not suppressed
(setq
whole (fix num)
fixfigs (strlen (itoa (abs whole)))
; # of characters to left of decimal, omitting "-" if negative
adj (- sf (if (zerop whole) 0 fixfigs)); # of sig-figs to adjust by
; for numbers between -1 and 1, 0 before decimal is not significant;
; + value = needs decimal place(s), - = round integer to ending 0('s)
sigfigged
(cond
((minusp adj); round last figure(s) to 0('s)
(itoa (* (atoi (rtos (/ num (expt 10.0 (- adj))) 2 0)) (expt 10 (- adj))))
); rounded-integer condition
((< 0 (abs num) 1); between -1 and 1, but not zero
(setq
sci (rtos (abs num) 1 (1- sf)); scientific notation without - if negative
ex (atoi (substr sci (+ (vl-string-position 45 sci) 2))); exponent at end
); setq
(rtos num 2 (1- (+ sf ex))); increase decimal places for leading 0's
); -1 to 1 non-zero condition
((rtos num 2 adj)); all others [including 0] -- with decimal places as needed
); cond & sigfigged
); setq
(setvar 'dimzin dimz)
sigfigged
); defun
A new version to hopefully account for such issues:
;; Round to Significant Figure - Lee Mac ;; Returns a string representation of a supplied numerical argument ;; rounded to a given number of significant figures (defun LM:sigfig ( n f / d e l r ) (cond ( (minusp n) (strcat "-" (LM:sigfig (abs n) f))) ( (setq d (getvar 'dimzin)) (setvar 'dimzin 0) (if (zerop n) (setq r (rtos 0 2 f)) (setq l (+ (/ (log n) (log 10)) 1e-8) l (fix (if (minusp l) (1- l) l)) e (expt 10.0 (- l f -1)) r (rtos (* (atof (rtos (/ n e) 2 0)) e) 2 (max (- f l 1) 0)) ) ) (setvar 'dimzin d) r ) ) )
_$ (LM:sigfig 234 5) "234.00" _$ (LM:sigfig 0.12343556 4) "0.1234" _$ (LM:sigfig -12.3456 4) "-12.35" _$ (LM:sigfig 0 4) "0.0000"
Thank you both Kent1Cooper & Lee Mac!
Kent1Cooper is correct about the rounding and both your code and Lee Mac's 2nd code work very well!
Your assistance is very much appreciated, I have not seen the maths behind that process before.
You both got me out of a jam!!!
Thanks again guys!
Kind Regards
Steve 🙂