Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Rounding a real number to 4 significant figures

4 REPLIES 4
SOLVED
Reply
Message 1 of 5
SteveGriffiths-HC
1833 Views, 4 Replies

Rounding a real number to 4 significant figures

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 🙂

4 REPLIES 4
Message 2 of 5
Lee_Mac
in reply to: SteveGriffiths-HC

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"

 

Message 3 of 5
Kent1Cooper
in reply to: Lee_Mac

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

Kent Cooper, AIA
Message 4 of 5
Lee_Mac
in reply to: Kent1Cooper

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"

 

Message 5 of 5
SteveGriffiths-HC
in reply to: Lee_Mac

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 🙂

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost