RepCad Posted November 29, 2020 Posted November 29, 2020 (edited) Hi all, I have a problem with product of two big numbers in Autolisp : (rtos (* 412866307 249513616) 2) it Returns : "-368000080" I could not find the reason of the problem, does someone know the reason of it? Edited November 29, 2020 by amir0914 Quote
rlx Posted November 29, 2020 Posted November 29, 2020 $ (rtos (* 412866307.0 249513616.0) 2) "1.0302E+17" _$ (rtos (* (float 412866307) (float 249513616)) 2) "1.0302E+17" _$ 1 Quote
Lee Mac Posted November 29, 2020 Posted November 29, 2020 Integers in AutoLISP are stored as 32-bit signed integers, which have an upper limit of (2^31)-1 = 2,147,483,647. Exceeding this limit will cause the sign bit to be flipped, causing the number to wrap around to -2^31 = -2,147,483,648. 1 Quote
RepCad Posted November 29, 2020 Author Posted November 29, 2020 (edited) 50 minutes ago, rlx said: $ (rtos (* 412866307.0 249513616.0) 2) "1.0302E+17" _$ (rtos (* (float 412866307) (float 249513616)) 2) "1.0302E+17" _$ Many thanks, I wanted to print it on a msgbox, but it nor appears in full : (setq num (rtos (* 412866307.0 249513616.0) 2)) (alert num) Is it possible to display full text on alert window : "103015765184136112" Edited November 29, 2020 by amir0914 Quote
rlx Posted November 29, 2020 Posted November 29, 2020 you can increase the precision with units command (or LUPREC) and /or use RTOS like (rtos i 2 8) but AutoCad will only display numbers to a certain max/min value and after that is switches automatically to scientific notation. from help RTOS: The rtos function returns a string that is the representation of number according to the settings of mode, precision, and the AutoCAD UNITMODE, DIMZIN, LUNITS, and LUPREC system variables. The mode and precision arguments correspond to the AutoCAD LUNITS and LUPREC system variables. If you omit the arguments,rtos uses the current settings of LUNITS and LUPREC. so (setq num (rtos (* 412866307.0 249513616.0) 2 16)) would give a few more decimals but unfortunately its still not enough for what you want. Not sure if its possible to first devide both numbers by lets say ten thousand and calculate before and after decimal point separately and join them afterwards. I don't have a degree in math like master Lee. 1 Quote
Stefan BMR Posted November 29, 2020 Posted November 29, 2020 (edited) 1 hour ago, rlx said: ... Not sure if its possible to first devide both numbers by lets say ten thousand and calculate before and after decimal point separately and join them afterwards. I don't have a degree in math like master Lee. I was about to bring this challenge up So, this is a way to multiply large positive numbers: (defun multip (a b / q m n r c l) (setq q (max (length a) (length b))) (repeat (- q (length a)) (setq a (cons 0 a)) ) (repeat (- q (length b)) (setq b (cons 0 b)) ) (setq c 0) (repeat q (setq q (1- q) m (cons (nth q a) m) n (cons (nth q b) n) r (+ c (apply '+ (mapcar '* m (reverse n)))) c (/ r 10) l (cons (rem r 10) l) ) ) (setq n (reverse n) m (reverse m) ) (while (setq m (cdr m)) (setq n (cdr n) r (+ c (apply '+ (mapcar '* m (reverse n)))) c (/ r 10) l (cons (rem r 10) l) ) ) (while (> c 0) (setq l (cons (rem c 10) l) c (/ c 10) ) ) (while (zerop (car l)) (setq l (cdr l))) l ) _$ (MULTIP '(4 1 2 8 6 6 3 0 7) '(2 4 9 5 1 3 6 1 6)) (1 0 3 0 1 5 7 6 5 1 8 4 1 3 6 1 1 2) _$ (MULTIP '(4 1 2 8 6 6 3 0 7 4 1 2 8 6 6 3 0 7 4 1 2 8 6 6 3 0 7) '(2 4 9 5 1 3 6 1 6 2 4 9 5 1 3 6 1 6 2 4 9 5 1 3 6 1 6)) (1 0 3 0 1 5 7 6 5 3 9 0 1 6 7 6 4 2 6 7 7 3 1 9 5 1 9 7 5 8 4 3 9 8 6 6 4 7 1 2 8 7 9 8 9 1 8 4 1 3 6 1 1 2) _$ More efficient would be to divide the original number in fractions of thousand. The lisp above will work if 10 is replaced by 1000. But I'm more interested of some clever codes. Mine is (almost) just a translation of the way the kids are doing multiplication in class. ... and the test function (defun test (a b / l1 l2) (if (and (eq (type a) 'int) (eq (type b) 'int) ) (progn (while (> a 0) (setq l1 (cons (rem a 10) l1) a (/ a 10) ) ) (while (> b 0) (setq l2 (cons (rem b 10) l2) b (/ b 10) ) ) ;;; (alert (apply 'strcat (mapcar 'itoa (multip l1 l2))) ;;; ) ) ) ) _$ (test 412866307 249513616) "103015765184136112" _$ Edited November 29, 2020 by Stefan BMR 2 Quote
rlx Posted November 29, 2020 Posted November 29, 2020 @Stefan BMR , nice job , I'm sure you-know-who probably can come up with a more generic formula but it's the end result that counts. 1 Quote
RepCad Posted November 29, 2020 Author Posted November 29, 2020 Thank you both, @Stefan BMR function was great. But another question, Should I use @Stefan BMR method if I want to use SUBSTR function.?? (setq num (rtos (* 412866307.0 249513616.0) 2)) (substr num 1 7) Returns : "1.03015" Whilst must return : "1030157" Quote
rlx Posted November 29, 2020 Posted November 29, 2020 stefans method obviously , but if you want to ditch the dot in a string you could use something like (vl-string-subst "" "." "1.234") 1 Quote
marko_ribar Posted December 1, 2020 Posted December 1, 2020 (edited) Here is my conversion... ;;;------------------------------------------------------------------;;; ;;; multp - sub function - multiplication of 2 numbers of any length ;;; ;;; ;;; ;;; Arguments : ;;; ;;; a - first number - type = string ;;; ;;; b - second number - type = string ;;; ;;; ;;; ;;; Return : ;;; ;;; r - resulting number - type = string ;;; ;;; ;;; ;;; Written by Marko Ribar, d.i.a. (architect) ;;; ;;;------------------------------------------------------------------;;; (defun multp ( a b / s ad bd dp an bn k c n l ll r rr ) (if (and (= (type a) 'STR) (/= a "") (= "" (vl-string-trim "-0123456789." a)) (= (type b) 'STR) (/= b "") (= "" (vl-string-trim "-0123456789." b))) (progn (if (or (and (minusp (atof a)) (not (minusp (atof b)))) (and (not (minusp (atof a))) (minusp (atof b)))) (setq s t) ) (if (or (zerop (atof a)) (zerop (atof b))) (setq r "0") (progn (setq a (vl-string->list a)) (setq b (vl-string->list b)) (setq ad a) (if (vl-position 46 ad) (while (/= (car ad) 46) (setq ad (cdr ad)) ) (setq ad nil) ) (setq bd b) (if (vl-position 46 bd) (while (/= (car bd) 46) (setq bd (cdr bd)) ) (setq bd nil) ) (if (or (vl-position 46 ad) (vl-position 46 bd)) (setq dp (+ (if ad (1- (length ad)) 0) (if bd (1- (length bd)) 0))) (setq dp 0) ) (setq an (vl-remove 45 (vl-remove 46 a))) (setq bn (vl-remove 45 (vl-remove 46 b))) (setq an (reverse an)) (setq bn (reverse bn)) (setq k 0) (foreach aa an (setq k (1+ k)) (setq c 0) (foreach bb bn (setq n (rem (+ c (* (atoi (chr aa)) (atoi (chr bb)))) 10)) (setq c (fix (/ (+ c (* (atoi (chr aa)) (atoi (chr bb)))) 10.0))) (if (zerop (fix (/ n 10.0))) (setq l (cons n l)) (progn (setq l (cons (rem n 10) l)) (setq c (fix (/ n 10.0))) ) ) ) (if (not (zerop c)) (setq l (cons c l)) ) (setq ll (cons (reverse l) ll)) (setq l nil) (repeat k (setq l (cons 0 l)) ) ) (setq n (apply 'max (mapcar 'length ll))) (setq ll (mapcar '(lambda ( x ) (if (= (length x) n) x (progn (repeat (- n (length x)) (setq x (append x (list 0)))) x))) ll)) (setq r (apply 'mapcar (cons '+ ll))) (setq c 0) (foreach x r (if (zerop (fix (/ (+ x c) 10.0))) (progn (setq rr (cons (+ x c) rr)) (setq c 0) ) (progn (setq rr (cons (rem (+ x c) 10) rr)) (setq c (fix (/ (+ x c) 10.0))) ) ) ) (if (not (zerop c)) (setq rr (cons c rr)) ) (setq k nil) (setq r (apply 'append (mapcar '(lambda ( x ) (if (null k) (setq k 1) (setq k (1+ k))) (if (/= k dp) (list (ascii (itoa x))) (list (ascii (itoa x)) 46))) (reverse rr)))) (setq r (reverse r)) (while (and (= (car r) 48) (/= (cadr r) 46)) (setq r (cdr r)) ) (if s (setq r (strcat "-" (vl-list->string r))) (setq r (vl-list->string r)) ) ) ) r ) ) ) (defun c:multp ( / a b ) (setq a (getstring "\nSpecify number a : ")) (while (or (= a "") (/= "" (vl-string-trim "-0123456789." a))) (prompt "\nInvalid a number specification...") (setq a (getstring "\nSpecify number a : ")) ) (setq b (getstring "\nSpecify number b : ")) (while (or (= b "") (/= "" (vl-string-trim "-0123456789." b))) (prompt "\nInvalid b number specification...") (setq b (getstring "\nSpecify number b : ")) ) (princ (strcat "\n" (multp a b))) (princ) ) Edited December 2, 2020 by marko_ribar 1 Quote
Stefan BMR Posted December 1, 2020 Posted December 1, 2020 10 minutes ago, marko_ribar said: Here is my conversion... Negative numbers are not implemented, but decimals are... Nice one Marko, but sometimes a "1" in front is missing. It might be the "c" variable that still holds something greater than 0. Command: MULTP Specify number a : 1235462574.32561 Specify number b : 845655123645487545852.65514 044775256050696071694271543803.8134001354 1 Quote
marko_ribar Posted December 1, 2020 Posted December 1, 2020 1 hour ago, Stefan BMR said: Nice one Marko, but sometimes a "1" in front is missing. It might be the "c" variable that still holds something greater than 0. Command: MULTP Specify number a : 1235462574.32561 Specify number b : 845655123645487545852.65514 044775256050696071694271543803.8134001354 Thanks Stefan for your input, I revised my code... M.R. 1 Quote
marko_ribar Posted December 2, 2020 Posted December 2, 2020 (edited) And here is very simple example of how to process list of number strings... ;;;--------------------------------------------------------------------------------------------------------------;;; ;;; multplst - sub function - successive multiplication numbers of any length stored in a list of number strings ;;; ;;; ;;; ;;; Requirements : Loaded (multp a b) sub-function ;;; ;;; ;;; ;;; Arguments : ;;; ;;; lst - list of number strings - type = list ; for ex. (setq lst '("2" "4" "6")) ;;; ;;; ;;; ;;; Return : ;;; ;;; r - resulting number - type = string ;;; ;;; ;;; ;;; AutoLisp synonym : ;;; ;;; (apply (function *) lst) => number (real or integer) ; lst - list of numbers (reals or integers) ;;; ;;; ;;; ;;; Example : ;;; ;;; (setq lst '("2" "4" "6")) ;;; ;;; (setq r (multplst lst)) => r = "48" ;;; ;;; (princ (strcat "\n" r)) => 48 ;;; ;;; (princ) ;;; ;;; ;;; ;;; Written by Marko Ribar, d.i.a. (architect) ;;; ;;;--------------------------------------------------------------------------------------------------------------;;; (defun multplst ( lst / r ) (setq r "1") (while (car lst) (setq r (multp r (car lst))) (setq lst (cdr lst)) ) r ) P.S. You have to have loaded (multp a b) sub-function I posted in my previous code... HTH. Regards, M.R. Edited December 3, 2020 by marko_ribar 1 Quote
RepCad Posted December 6, 2020 Author Posted December 6, 2020 Thanks to marko_ribar, that was great. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.