Đến nội dung


Hình ảnh
- - - - -

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


  • Please log in to reply
7 replies to this topic

#1 Polyline

Polyline

    biết lệnh mirror

  • Members
  • PipPipPip
  • 159 Bài viết
Điểm đánh giá: 18 (tàm tạm)

Đã gửi 05 July 2013 - 05:09 PM

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)
)
)


  • 0

#2 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5454 Bài viết
Điểm đánh giá: 2626 (tuyệt vời)

Đã gửi 05 July 2013 - 06:39 PM

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?


  • 0

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#3 Tue_NV

Tue_NV

    KS Võ Quang Tuệ

  • Moderator
  • PipPipPipPipPipPipPip
  • 4296 Bài viết
Điểm đánh giá: 3804 (đỉnh cao)

Đã gửi 05 July 2013 - 10:22 PM

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)
)
)
)

  • 2

#4 Doan Van Ha

Doan Van Ha

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 5454 Bài viết
Điểm đánh giá: 2626 (tuyệt vời)

Đã gửi 06 July 2013 - 07:52 AM

Trong 4 điều kiện bác Tue_NV có thể bỏ đi 2 điều kiện đầu. Thậm chí chỉ cần để lại 1 điều kiện INT.


  • 0

* Chỉ nên yêu cầu Lisp khi bạn làm việc đó mất cả ngày nhưng họ chỉ viết 1 giờ. Đừng nêu yêu cầu Lisp khi bạn chỉ làm 1 giờ nhưng bắt họ phải mất cả ngày.

* Nhờ viết lisp cũng như đi khám bệnh. Chỉ gởi căn cước và than sắp chết thì không bác sỹ nào cứu sống được.


#5 Polyline

Polyline

    biết lệnh mirror

  • Members
  • PipPipPip
  • 159 Bài viết
Điểm đánh giá: 18 (tàm tạm)

Đã gửi 06 July 2013 - 08:30 AM

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?


  • 0

#6 ndtnv

ndtnv

    biết lệnh minsert

  • Members
  • PipPipPipPipPipPip
  • 437 Bài viết
Điểm đánh giá: 384 (khá)

Đã gửi 06 July 2013 - 02:26 PM

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)

  • 3

#7 Polyline

Polyline

    biết lệnh mirror

  • Members
  • PipPipPip
  • 159 Bài viết
Điểm đánh giá: 18 (tàm tạm)

Đã gửi 08 July 2013 - 02:22 PM

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?


  • 0

#8 gia_bach

gia_bach

    biết lệnh adcenter

  • CADViet Team
  • PipPipPipPipPipPipPip
  • 1436 Bài viết
Điểm đánh giá: 1426 (rất tốt)

Đã gửi 08 July 2013 - 02:46 PM

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.c...arch_app=forums


  • 1