Chuyển đến nội dung
Diễn đàn CADViet
  • Thông báo

    • Nguyen Hoanh

      CADViet đã hoàn tất nâng cấp   14/09/2017

      Chào các bạn, CADViet đã hoàn tất việc nâng cấp lên phiên bản mới. Tất cả các chức năng đã hoạt động theo kỳ vọng của ban quản trị. Nếu có vấn đề gì cần phản hồi, các bản post ở đây nhé: Trân trọng, Nguyễn Hoành.
Đăng nhập để thực hiện theo  
Polyline

[Hỏi] Cần rút gọn code

Các bài được khuyến nghị

Khi viết Lisp, đôi khi ta cần phân tích một số ra các số mũ của 2, điển hình là hàm INITGET.
Ví dụ ai đó viết (initget 53), thì hoàn toàn không dễ hiểu chút nào.
Nhưng nếu ai đó viết (initget (+ 1 4 16 32)) thì dễ hiểu hơn nhiều, và có thể dùng trợ giúp của AutoLisp để tra cứu tác dụng của nó là gì.
 
Mình có viết một đoạn code để làm việc này nhưng chưa được vừa ý, vì nó dài dòng quá. Bà con cô bác nào có ý tưởng rút gọn nó lại bớt được không?


;Hàm con
;nhận vào một số nguyên dương nhỏ hơn (expt 2 21) = 2097152
;trả về một danh sách, là các mã bit thành phần
;
;Ví dụ (hamcon-bit-1 53) sẽ trả về (1 4 16 32)
;(hamcon-bit-1 2097151)
;Nếu không phải là số nguyên dương, hàm sẽ trả về nil
(defun hamcon-bit-1(n / ds)
(if (numberp n)
(if (= (type n) 'INT)
(if (not(minusp n))
(if (< n 2097152)
(progn
(setq ds '())
(while (> n 0)
(cond
((>= n (expt 2 20))(progn (setq ds (append ds (list (expt 2 20))) n (- n (expt 2 20)))));1048576
((>= n (expt 2 19))(progn (setq ds (append ds (list (expt 2 19))) n (- n (expt 2 19))))); 524288
((>= n (expt 2 18))(progn (setq ds (append ds (list (expt 2 18))) n (- n (expt 2 18))))); 262144
((>= n (expt 2 17))(progn (setq ds (append ds (list (expt 2 17))) n (- n (expt 2 17))))); 131072
((>= n (expt 2 16))(progn (setq ds (append ds (list (expt 2 16))) n (- n (expt 2 16))))); 65536
((>= n (expt 2 15))(progn (setq ds (append ds (list (expt 2 15))) n (- n (expt 2 15))))); 32768
((>= n (expt 2 14))(progn (setq ds (append ds (list (expt 2 14))) n (- n (expt 2 14))))); 16384
((>= n (expt 2 13))(progn (setq ds (append ds (list (expt 2 13))) n (- n (expt 2 13))))); 8192
((>= n (expt 2 12))(progn (setq ds (append ds (list (expt 2 12))) n (- n (expt 2 12))))); 4096
((>= n (expt 2 11))(progn (setq ds (append ds (list (expt 2 11))) n (- n (expt 2 11))))); 2048
((>= n (expt 2 10))(progn (setq ds (append ds (list (expt 2 10))) n (- n (expt 2 10))))); 1024
((>= n (expt 2 9))(progn (setq ds (append ds (list (expt 2 9))) n (- n (expt 2 9))))); 512
((>= n (expt 2 8))(progn (setq ds (append ds (list (expt 2 8))) n (- n (expt 2 8))))); 256
((>= n (expt 2 7))(progn (setq ds (append ds (list (expt 2 7))) n (- n (expt 2 7))))); 128
((>= n (expt 2 6))(progn (setq ds (append ds (list (expt 2 6))) n (- n (expt 2 6))))); 64
((>= n (expt 2 5))(progn (setq ds (append ds (list (expt 2 5))) n (- n (expt 2 5))))); 32
((>= n (expt 2 4))(progn (setq ds (append ds (list (expt 2 4))) n (- n (expt 2 4))))); 16
((>= n (expt 2 3))(progn (setq ds (append ds (list (expt 2 3))) n (- n (expt 2 3))))); 8
((>= n (expt 2 2))(progn (setq ds (append ds (list (expt 2 2))) n (- n (expt 2 2))))); 4
((>= n (expt 2 1))(progn (setq ds (append ds (list (expt 2 1))) n (- n (expt 2 1))))); 2
((>= n (expt 2 0))(progn (setq ds (append ds (list (expt 2 0))) n (- n (expt 2 0))))); 1
))

(reverse ds))
(progn
(princ (strcat "\n\n\n*** (Hamcon-bit-1 n): Lỗi do số nhập vào " (rtos n 2 ) " lớn hơn 1048576 ***\n"))
nil)
)
(progn
(princ "\n\n\n*** (Hamcon-bit-1 n): Lỗi do số nhập vào âm ***\n")
nil)
)
(progn
(princ "\n\n\n*** (Hamcon-bit-1 n): Lỗi do số nhập vào không nguyên ***\n")
nil)
)
(progn
(princ "\n\n\n*** (Hamcon-bit-1 n): Lỗi do nhập vào không phải là số ***\n")
nil)
)
)

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Với những hàm kiểu này, nhiều khả năng dùng phương pháp đệ quy thì code sẽ rất ngắn gọn.

Mình chưa rảnh để thử nhưng hy vọng là được. Bạn thử xem sao?

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Rút gọn code lại cho bạn chủ píc đây:

 

(defun hamcon-bit-1tue (n / ds)
(setq ds '() i 20)
(if (and (numberp n) (not(minusp n)) (= (type n) 'INT) (< n 2097152))
(while (> n 0)
(if (>= n (expt 2 i)) (setq ds (cons (expt 2 i) ds) n (- n (expt 2 i))))
  (setq i (1- i))
))
ds)
(defun hamcon-bit-1tue (n / ds)
(setq ds '() i 20)
(if (and (numberp n) (not(minusp n)) (= (type n) 'INT) (< n 2097152))
(while (> n 0)
(if (>= n (expt 2 i)) (setq ds (cons (expt 2 i) ds) n (- n (expt 2 i))))
  (setq i (1- i))
 
(defun hamcon-bit-1tue (n / ds)
(if (and (numberp n) (not(minusp n)) (= (type n) 'INT) (< n 2097152))
(progn
(setq ds '() i 20)
(while (> n 0)
(if (>= n (expt 2 i)) (setq ds (cons (expt 2 i) ds) n (- n (expt 2 i))))
  (setq i (1- i))
)
ds
)
)
 
(defun hamcon-bit-1tue (n / ds)
(if (and (numberp n) (not(minusp n)) (= (type n) 'INT) (< n 2097152))
(progn
(setq ds '() i 20)
(while (> i 0)
(if (>= n (expt 2 i)) (setq ds (cons (expt 2 i) ds) n (- n (expt 2 i))))
  (setq i (1- i))
)
  (cons n ds)
)
)
)
  • Vote tăng 2

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Cám ơn bác Tue, code đã tốt hơn nhiều rồi!
Nhân tiện cho mình hỏi một chút: Mình không tìm thấy định nghĩa của các kiểu dữ liệu của AutoLisp.
Ví dụ: Kiểu INT, mình hiểu nó là số nguyên, hàm (GetInt thì chỉ cho phép dải từ -32,768 đến +32,767. Vậy giới hạn của kiểu INT là bao nhiêu?

Tương tự, các kiểu dữ liệu khác REAL, STR không rõ giới hạn của nó như thế nào, hay là không giới hạn?

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Cám ơn bác Tue, code đã tốt hơn nhiều rồi!

Nhân tiện cho mình hỏi một chút: Mình không tìm thấy định nghĩa của các kiểu dữ liệu của AutoLisp.

Ví dụ: Kiểu INT, mình hiểu nó là số nguyên, hàm (GetInt thì chỉ cho phép dải từ -32,768 đến +32,767. Vậy giới hạn của kiểu INT là bao nhiêu?

Tương tự, các kiểu dữ liệu khác REAL, STR không rõ giới hạn của nó như thế nào, hay là không giới hạn?

Kiểu INT chiếm 4 byte, từ -2^31 => +2^31-1

tức là từ -2,147,483,648 đến 2,147,483,647

Tuy nhiên hàm getint chỉ nhận giá trị của số nguyên 2 byte -2^15 => +2^15-1

tức là từ  -32,768 đến +32,767

Trên hệ thống máy tính thông thường, một số dấu phẩy động nhị phân định dạng ‘độ chính xác kép’ (64 bit) có phần định trị 52 bit (thực ra là 53 bit vì trong đó có một bit 1 luôn luôn có nhưng không thể hiện tường minh), phần số mũ gồm 11 bit và 1 bit dấu. Tầm số dương mà định dạng này có thể biểu diễn được là khoảng từ 10^−308 đến 10^308 (vì 308 xấp xỉ bằng 1023 × log10(2) và tầm số mũ của định dạng độ chính xác kép là [−1022,1023]). Toàn tầm hiển thị của định dạng độ chính xác kép là khoảng từ −10^308 đến +10^308

Nên tính i 1 lần thay vì 3 lần gọi hàm expt

Dùng hàm bit lsh sẽ nhanh hơn hàm expt

 

(defun hamcon-bit-1 (n / ds)
(setq ds '() i (lsh 2 20))
(if (and (numberp n) (not(minusp n)) (= (type n) 'INT) (< n 2097152))
(while (> n 0)
(if (>= n i) (setq ds (cons i ds) n (- n i)))
  (setq i (lsh i -1))
))
ds)
  • Vote tăng 3

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Oh, bác ndtnv uyên thâm quá! Bác cho hỏi một chút: Trong Autolisp, làm thế nào để biết hàm này chạy nhanh hơn hàm khác hả bác?

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Oh, bác ndtnv uyên thâm quá! Bác cho hỏi một chút: Trong Autolisp, làm thế nào để biết hàm này chạy nhanh hơn hàm khác hả bác?

Bác NDT... là C++ prồ mà.

 

Trong Autolisp, làm thế nào để biết hàm này chạy nhanh hơn hàm khác hả bác?

- search trong CadViet với từ khóa : (getvar "millisecs") link : http://www.cadviet.com/forum/custom/search.html?search_term=millisecs&search_app=forums

  • Vote tăng 1

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Tạo một tài khoản hoặc đăng nhập để nhận xét

Bạn cần phải là một thành viên để lại một bình luận

Tạo tài khoản

Đăng ký một tài khoản mới trong cộng đồng của chúng tôi. Điều đó dễ mà.

Đăng ký tài khoản mới

Đăng nhập

Bạn có sẵn sàng để tạo một tài khoản ? Đăng nhập tại đây.

Đăng nhập ngay

Đăng nhập để thực hiện theo  

×