Chuyển đến nội dung
Diễn đàn CADViet
Doan Van Ha

Các lỗi "oái oăm" trong LISP!!!

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

Có thể có bạn đã gặp và đã biết, nhưng cũng có thể có bạn chưa biết. Dưới đây là vài lỗi "oái oăm" trong LISP. Cứ ngỡ nó bình thường nhưng đôi lúc nó khiến bạn mất một đống thời gian vì chúng:

1) Hãy thử suy nghĩ xem: (cos (/ pi 2))=0 là đúng hay sai?

2) Cho: (setq a nil). Hãy thử suy nghĩ xem: (< a 100) cho kết quả là gì?

Ai biết thêm thì post lên cho mọi người.

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ó thể có bạn đã gặp và đã biết, nhưng cũng có thể có bạn chưa biết. Dưới đây là vài lỗi "oái oăm" trong LISP. Cứ ngỡ nó bình thường nhưng đôi lúc nó khiến bạn mất một đống thời gian vì chúng:

1) Hãy thử suy nghĩ xem: (cos (/ pi 2))=0 là đúng hay sai?

2) Cho: (setq a nil). Hãy thử suy nghĩ xem: (< a 100) cho kết quả là gì?

Ai biết thêm thì post lên cho mọi người.

1. Bản thân pi là một số xấp xỉ vậy nên (cos (/ pi 2)) là một số xấp xỉ là đương nhiên. Nó không thể ra giá trị chính xác bằng 0

2. nil luôn nhỏ hơn mọi số. Cái này ta phải bắt lỗi thôi vì phép so sánh chỉ dùng với cùng một kiểu biến

 

Còn một số điều khó hiểu nữa (chứ không được coi là lỗi) mà bản thân chúng ta chưa hiểu hết về bản chất của lisp mà thôi

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ó thể có bạn đã gặp và đã biết, nhưng cũng có thể có bạn chưa biết. Dưới đây là vài lỗi "oái oăm" trong LISP. Cứ ngỡ nó bình thường nhưng đôi lúc nó khiến bạn mất một đống thời gian vì chúng:

1) Hãy thử suy nghĩ xem: (cos (/ pi 2))=0 là đúng hay sai?

2) Cho: (setq a nil). Hãy thử suy nghĩ xem: (< a 100) cho kết quả là gì?

Ai biết thêm thì post lên cho mọi người.

 

1. Bản thân pi là một số xấp xỉ vậy nên (cos (/ pi 2)) là một số xấp xỉ là đương nhiên. Nó không thể ra giá trị chính xác bằng 0

2. nil luôn nhỏ hơn mọi số. Cái này ta phải bắt lỗi thôi vì phép so sánh chỉ dùng với cùng một kiểu biến

 

Còn một số điều khó hiểu nữa (chứ không được coi là lỗi) mà bản thân chúng ta chưa hiểu hết về bản chất của lisp mà thôi

oái oăm" trong LISP :

 

1) (equal (cos (/ pi 2)) 0 0.1) -> T

 

2) (setq a nil) : (if (numberp a) (< a 100) nil) -> ?

  • 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
1. Bản thân pi là một số xấp xỉ vậy nên (cos (/ pi 2)) là một số xấp xỉ là đương nhiên. Nó không thể ra giá trị chính xác bằng 0

2. nil luôn nhỏ hơn mọi số. Cái này ta phải bắt lỗi thôi vì phép so sánh chỉ dùng với cùng một kiểu biến

 

Còn một số điều khó hiểu nữa (chứ không được coi là lỗi) mà bản thân chúng ta chưa hiểu hết về bản chất của lisp mà thôi

(cos (/ pi 2)) /= 0

nhưng (sin (/ pi 2) = 1 đấy!

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
oái oăm" trong LISP :

 

1) (equal (cos (/ pi 2)) 0 0.1) -> T

 

2) (setq a nil) : (if (numberp a) (< a 100) nil) -> ?

(cos (/ pi 2)) = 6.12323e-017 => (equal (cos (/ pi 2)) 0 0.1)->T => chuẩn

 

(if (numberp a) t nil) -> nil => a không phải là 1 number =>(if (numberp a) (< a 100) nil) -> nil => chuẩn. Tuy nhiên nil đặc biệt ở chỗ có thể so sánh với number và luôn nhỏ hơn anynumber

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
(cos (/ pi 2)) /= 0

nhưng (sin (/ pi 2) = 1 đấy!

Có thể hai hàm sin và cos có cách tính khác nhau vì tan = sin/cos trường hợp này sẽ ra vô cùng mà máy tính thì không có số vô cùng. Chậc, tính toán trên máy tính là tính gần đúng chứ không như tính theo giải tích

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
(cos (/ pi 2)) /= 0

nhưng (sin (/ pi 2) = 1 đấy!

Theo Tue_NV thì cũng không có gì lạ cả.

Máy tính có lẽ đã định nghĩa hàm cos và sin dưới dạng tổng của 1 chuỗi số vô hạn

Định nghĩa bằng chuỗi

Kết quả của 1 phép tính cộng, chia và lũy thừa.

Sai số là tất nhiên :leluoi:

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ó thể hai hàm sin và cos có cách tính khác nhau vì tan = sin/cos trường hợp này sẽ ra vô cùng mà máy tính thì không có số vô cùng. Chậc, tính toán trên máy tính là tính gần đúng chứ không như tính theo giải tích

Không phải chỉ LISP tính sin, cos, tan... gần đúng theo hình thức khai triển chuỗi (có lẽ thế) mà Excel... cũng vậy.

Vấn đề đưa ra là nhằm mục đích cảnh báo những "sơ ý chết người" khi sử dụng các hàm đó.

Ví dụ 1: ta viết một đoạn lisp như sau:

(cond ((< a 100) (setq b 1))

((>= a 100) (setq b 2)))

Khi kết quả trả về là b=1 thì ta cứ ngỡ a<100, nhưng đôi lúc a=nil, thành ra chương trình của ta có thể sai bét.

Ví dụ 2: khi ta xét 2 đường thẳng có vuông góc với nhau hay không?

- Nếu xét bằng hàm sin của góc tạo bởi 2 đường thẳng đó thì nó bằng 1, và điều này đúng.

- Nếu xét bằng hàm cos của góc tạo bởi 2 đường thẳng đó thì nó bằng... 6.12303e-017, và điều này nếu không để ý thì dễ suy ra chúng không vuông góc nhau. Mà thực tế là chúng vuông góc nhau.

Điều tôi muốn đưa lên diễn đàn chính là để cảnh báo thôi, vì chúng ta có thể "sơ ý" như trên, mà tôi đã là 1 nạn nhân của cả 2 vấn đề trên.

Mong bạn nào có phát hiện hay thì post lên để mọi người cùng... hưởng lợi.

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

Một ví dụ cơ bản nữa: (/ 10 4) = 2 tức kết quả sẽ ra cùng kiểu với 2 tham số đưa vào (int). Tuy nhiên trường hợp này kết quả sẽ phải là kiểu khác (real) . Vậy nên ít nhất 1 trong 2 tham số phải có cùng kiểu với kết quả ví dụ (/ 10.0 4) = 2.5 . Có thể mở rộng ra thêm nhiều ví dụ khác nữa...

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ẽ 1 đường Mline bằng hàm command thì có thể lấy record đối tượng của nó bằng bằng hàm entget.

mình vẽ lại đường Mline đó bằng entmake theo record thu được ở trên thì vẫn vẽ được đối tượng bình thường. nhưng lạ ở chỗ không thể lấy được record của đối tượng mới này dù vẫn thu được ename bằng entsel. kết quả trả về nil.

Cũng không có cách gì để tạo 1 Mline bằng entmake. Kết quả thu luôn là 1 dòng thông báo lỗi. cú thật <_<

(entmakex '((0 . "MLINE")

(100 . "AcDbEntity")

(67 . 0)

(8 . "0")

(100 . "AcDbMline")

(2 . "STANDARD")

(40 . 20.0)

(70 . 0)

(71 . 1)

(72 . 3)

(73 . 2)

(10 -501.575 84.252 0.0)

(210 0.0 0.0 1.0)

(11 -501.575 84.252 0.0)

(12 0.957319 0.289032 0.0)

(13 -0.289032 0.957319 0.0)

(74 . 2)

(41 . 0.0)

(41 . 0.0)

(75 . 0)

(74 . 2)

(41 . -20.0)

(41 . 0.0)

(75 . 0)

(11 972.588 529.329 0.0)

(12 0.310483 -0.950579 0.0)

(13 0.462613 0.88656 0.0)

(74 . 2)

(41 . 0.0)

(41 . 0.0)

(75 . 0)

(74 . 2)

(41 . -27.9716)

(41 . 0.0)

(75 . 0)

(11 1174.77 -89.686 0.0)

(12 0.310483 -0.950579 0.0)

(13 0.950579 0.310483 0.0)

(74 . 2)

(41 . 0.0)

(41 . 0.0)

(75 . 0)

(74 . 2)

(41 . -20.0)

(41 . 0.0)

(75 . 0)))

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
E cop nguyên hàng của bác vào và vẫn thấy ra em Mline đẹp đẽ bác ạ :|

giờ bạn chạy tiếp cái này sẽ thấy điều lạ lùng (entget(car(entsel)))

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

Mình tiếp tục trở thành nạn nhân của 1 trường hợp cực kỳ oái oăm!

Hay tại mình đã hiểu sai điều gì chăng. có bác nào bị truờng hợp thế này chưa?

errorts.jpg

Mình có 2 Vector VecT1 và VecT2. Giá trị của chúng đuợc định như trong hình

vậy mà không hiểu sao góc hợp bởi 2 vector đó cứ lớn hơn 0 như vậy. với giá trị 0.95 quy ra độ nó gần 50độ chứ có ít đâu :(

mặt khác, khi mình gõ (angle '(0.25788 0.952772)'(0.25788 0.952772)) vào command thì kết quả trả về 0

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

E thì đang phân vân không biết làm sao trong lệnh Angle nó lại hiểu được 2 đối số của bác là vectơ nhỉ ^^

  • 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

Và đây là lỗi trên Cad 2010 (các phiên bản khác chưa k/tra)

 

Khi đặt tên biến là n

VD: (setq n 5)

sau khi gọi lệnh (vl-cmdf "_.-boundary" "_A" "_I" "_N" "" "" "_non" pt "")

CAD reset (xóa) biến n thành NIL.

 

(defun c:test(/ pt)
 (setq n 5)
 (setq pt (getpoint "\nPick point: "))
 (vl-cmdf "_.-boundary" "_A" "_I" "_N" "" "" "_non" pt "")
 (if n (princ n) (princ "Gia tri n la NIL"))
 (princ))

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à đây là lỗi trên Cad 2010 (các phiên bản khác chưa k/tra)

 

Khi đặt tên biến là n

VD: (setq n 5)

sau khi gọi lệnh (vl-cmdf "_.-boundary" "_A" "_I" "_N" "" "" "_non" pt "")

CAD reset (xóa) biến n thành NIL.

 

(defun c:test(/ pt)
 (setq n 5)
 (setq pt (getpoint "\nPick point: "))
 (vl-cmdf "_.-boundary" "_A" "_I" "_N" "" "" "_non" pt "")
 (if n (princ n) (princ "Gia tri n la NIL"))
 (princ))

Tôi có kiểm tra trên 2004 và 2007 nhưng không lỗi, còn 2010 chưa cài nên botay.com bác ạ

  • 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

Và đây là lỗi trên Cad 2010 (các phiên bản khác chưa k/tra)

 

Khi đặt tên biến là n

VD: (setq n 5)

sau khi gọi lệnh (vl-cmdf "_.-boundary" "_A" "_I" "_N" "" "" "_non" pt "")

CAD reset (xóa) biến n thành NIL.

 

(defun c:test(/ pt)
 (setq n 5)
 (setq pt (getpoint "\nPick point: "))
 (vl-cmdf "_.-boundary" "_A" "_I" "_N" "" "" "_non" pt "")
 (if n (princ n) (princ "Gia tri n la NIL"))
 (princ))

- E đã kiểm tra trên cad 07,08 và 12 thì không có lỗi trên

  • 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ôi có kiểm tra trên 2004 và 2007 nhưng không lỗi, còn 2010 chưa cài nên botay.com bác ạ

- E đã kiểm tra trên cad 07,08 và 12 thì không có lỗi trên

Cám ơn các bạn.

Như vậy chỉ Cad 2010 bị lỗi này ?

Hay Win của tui bị lỗi ? (XP SP3)

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à đây là lỗi trên Cad 2010 (các phiên bản khác chưa k/tra)

 

Khi đặt tên biến là n

VD: (setq n 5)

sau khi gọi lệnh (vl-cmdf "_.-boundary" "_A" "_I" "_N" "" "" "_non" pt "")

CAD reset (xóa) biến n thành NIL.

 

(defun c:test(/ pt)
 (setq n 5)
 (setq pt (getpoint "\nPick point: "))
 (vl-cmdf "_.-boundary" "_A" "_I" "_N" "" "" "_non" pt "")
 (if n (princ n) (princ "Gia tri n la NIL"))
 (princ))

Trên CAD 10

 

Command: test

Pick point: _.-boundary
Specify internal point or [Advanced options]: _A
Enter an option [boundary set/Island detection/Object type]: _I
Do you want island detection? [Yes/No] <Y>: _N
Enter type of ray casting [Nearest/+X/-X/+Y/-Y/Angle] <+X>:
Enter an option [boundary set/Island detection/Object type]:
Specify internal point or [Advanced options]: _non Selecting everything...
Selecting everything visible...
Analyzing the selected data...

Specify internal point or [Advanced options]:
BOUNDARY created 1 polyline
Command: 5

  • 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

em cũng đang xài Cad2010 - XPSP3, nhưng không thấy lỗi như của bác. Nhưng những lỗi kiểu như thế này thỉnh thoảng em cũng gặp. trong truờng hợp đó em thuờng tắt cad đi rồi mở lại thì không bị lỗi nữa.

  • 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

em cũng đang xài Cad2010 - XPSP3, nhưng không thấy lỗi như của bác. Nhưng những lỗi kiểu như thế này thỉnh thoảng em cũng gặp. trong truờng hợp đó em thuờng tắt cad đi rồi mở lại thì không bị lỗi nữa.

Cám ơn các bác đã trả lời.

 

Thử k/tra trên 1 số máy cài Cad2010 - XPSP3 thì có cái bị lỗi có cái không. <_<

 

Đã tìm ra vấn đề.

(do đặt tên biến toàn cục trong 1 hàm sử dụng REATOR)

 

Lisp tưởng là đơn giản nhưng cũng dễ bị "tẩu hỏa nhập ma".

Chỉnh sửa theo gia_bach

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

Mọi người bắt bệnh hộ ketxu vụ này xem do đâu với, e nghĩ mãi chưa thông:

1- Có 1 hàm setvar đơn giản :

(defun setvars()(setvar "pickfirst" 1))

=> Test trên command OK. Gọi trực tiếp từ hàm khác OK

 

2 - Viết sự kiện cho nó khi click vào 1 nút trong DCL :

(defun c:Test (/ fl ret dcl_id) 
 (vl-load-com)
 (setq fl (vl-filename-mktemp "mip" nil ".dcl"))
 (setq  ret (open fl "w"))
 (mapcar
'(lambda (x) (write-line x ret))
(list
"test_DCL : dialog {label=\"Test\"; width = 40;fixed_width = true;"
":button {label = \"Tho\U+00E1t\"; is_cancel = true;fixed_width = true;width = 1;}"   
":button {label = \"Setvar Test\";fixed_width = true;width = 1;key = \"kTest\";}"
"}"
)   
 )
 (setq ret (close ret))
 (if (and (not (minusp (setq dcl_id (load_dialog fl))))
      	(new_dialog "test_DCL" dcl_id)
 	)
(progn   

 (action_tile "kTest" "(setvars)") ;Su kien duy nhat


 	(setq dlg_Exit (start_dialog))  
) ;_ end of progn
 ) ;_ end of if
 (unload_dialog dcl_id) 
 (vl-file-delete fl)
ret
)

=> Chạy : ; error: AutoCAD variable setting rejected: "Pickfirst" 1

3- Đổi lại hàm ở 1 :

(defun setvars()(setvar "pickadd" 1))

=> CHạy : mượt

 

4- Không thông qua hàm mà cho trực tiếp vào code

thay : (action_tile "kTest" "(setvars)")

thành : (action_tile "kTest" "(setvar \"Pickfirst\" 1)")

=> Ẳng

 

5 - Thay : (action_tile "kTest" "(setvar \"Pickfirst\" 1)")

thành : (action_tile "kTest" "(setvar \"Snapang\" 1)")

=> OK

 

==>????

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

Mọi người bắt bệnh hộ ketxu vụ này xem do đâu với, e nghĩ mãi chưa thông:

....

(defun c:Test (/ fl ret dcl_id)
 (vl-load-com)
 (setq fl (vl-filename-mktemp "mip" nil ".dcl"))
 (setq  ret (open fl "w"))
 (mapcar
'(lambda (x) (write-line x ret))
(list
"test_DCL : dialog {label=\"Test\"; width = 40;fixed_width = true;"
":button {label = \"Tho\U+00E1t\"; is_cancel = true;fixed_width = true;width = 1;}"  
":button {label = \"Setvar Test\";fixed_width = true;width = 1;key = \"kTest\";}"
"}"
)  
 )
 (setq ret (close ret))
 (if (and (not (minusp (setq dcl_id (load_dialog fl))))
  		(new_dialog "test_DCL" dcl_id)
 	)
(progn  

 (action_tile "kTest" "(setvars)") ;Su kien duy nhat


 	(setq dlg_Exit (start_dialog))  
) ;_ end of progn
 ) ;_ end of if
 (unload_dialog dcl_id)
 (vl-file-delete fl)
ret
)

=> Chạy : ; error: AutoCAD variable setting rejected: "Pickfirst" 1

....

==>????

Có 1 vài hàm không thể thực hiện (Restricted) khi 1 hộp thoại (Dialog) đang được mở.

Functions Restricted When a Dialog Box Is Open

While a dialog box is active—that is, during the start_dialog call—you cannot call any function that requires user input on the AutoCAD command line, or affects the display outside the dialog box (for example, in the AutoCAD graphics window). This restriction includes functions that write text, such as print, princ, and prin1.

You can issue ssget calls, as long as you do not use any options that require user input.

If your program calls one of the restricted functions between the start_dialog and done_dialog calls, AutoCAD terminates all dialog boxes and displays the following error message: AutoCAD rejected function

 

có thể khắc phục bằng cách lưu vào biến, sau khi đóng hộp thoại mới gọi hàm thực thi.

(action_tile "kTest" "(setq pick 1)(done_dialog 1)") ;Su kien duy nhat

...

(vl-file-delete fl)

(if (= pick 1)(setvar "pickfirst" 1))

...

  • 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

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

×