找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3227|回复: 16

[讨论]:渐近法: 一种有趣的编程思路

[复制链接]
发表于 2005-11-12 09:11:14 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
通常写程序,算法都是力求精确,一步到位的。这样对于cad中的几何应用,就难免需要了解曲线方程、求解这些,本人的数学功底太浅,象求解两圆/弧切线这样的问题,已经超出了本人的能力。
前几天忽然想到,尽管不能一次得到结果,但可以用逐次接近的办法,从一段弧上的点切到另一段弧,然后再切回来,这样重复即会越来越接近正确的结果,理论上,这样永远不会得到精确的结果,将进入无穷循环,但是cad使用双精度浮点数,是有精度极限的!只要达到了cad的精度极限,结果与精确计算无异!
于是写了以下程序验证,只使用了最简单的几何运算,加入循环算法,相信不会比精确求解更复杂,结果有些出乎意料,原以为会需要很多次循环,实际循环不超过6至7次即得到精确结果,运行时间完全可以忽略不计。
这个方法可称为——渐近法,我觉得满有意义,有可能通过这个思路,以简单的技巧解决相对复杂的问题,发在这里共享一下,有所启发就好,如果能深入探讨解决一些实际问题就更好啦。


  1.   [FONT=courier new]
  2. ;;;用渐近法画两圆/弧的切线
  3. ;;;20051111
  4. (defun c:tantan (/        ANG CEN1 CEN2 ENS1 ENS2        N PT01 PT02 PT1        PT2 PT3        PT4 RAD1
  5.               RAD2)
  6.   (setq        ens1 (entsel "\n1st arc: ")
  7.         ens2 (entsel "\n2nd arc: ")
  8.   )
  9.   (mapcar 'set '(en1 pt1) ens1)
  10.   (mapcar 'set '(en2 pt2) ens2)
  11.   (setq        cen1 (osnap pt1 "cen")
  12.         cen2 (osnap pt2 "cen")
  13.         pt1  (osnap pt1 "nea")
  14.         pt2  (osnap pt2 "nea")
  15.         rad1 (distance cen1 pt1)
  16.         rad2 (distance cen2 pt2)
  17.         n    0
  18.   )
  19.   (while (and (not (equal pt1 pt01 1e-99))        ;渐近循环
  20.               (not (equal pt2 pt02 1e-99))
  21.          )
  22.     (setq pt01 pt1
  23.           pt02 pt2
  24.           n    (1+ n))
  25.     (setq ang  (angle pt1 pt2)
  26.           pt3  (polar cen1 (+ ang (* 0.5 pi)) 10.0)
  27.           pt3  (inters pt1 pt2 cen1 pt3 nil)
  28.           pt1  (polar cen1 (angle cen1 pt3) rad1)
  29.     )
  30.     (setq ang (angle pt1 pt2)
  31.           pt4 (polar cen2 (+ ang (* 0.5 pi)) 10.0)
  32.           pt4 (inters pt1 pt2 cen2 pt4 nil)
  33.           pt2 (polar cen2 (angle cen2 pt4) rad2)
  34.     )
  35.   )
  36.   (command "line" "non" pt1 "non" pt2 "")
  37.   (princ "\ncount: ")
  38.   (princ n)
  39.   (princ)
  40. )





  41.   [/FONT]
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
发表于 2005-11-12 10:16:20 | 显示全部楼层
顶一下,其实逼近的求法在论坛之前也有不少帖子。
提个建议,while条件中应对n有个限制,否则可能会进入死循环
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-11-12 11:13:56 | 显示全部楼层
最初由 狂刀 发布
[B]
提个建议,while条件中应对n有个限制,否则可能会进入死循环 [/B]

这种方法容易进入死循环,因此在算法上应当慎重,加次数限制是在调试的时候,但不利于精确。有效的算法应能自行达到精度,结束循环。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-11-12 14:34:48 | 显示全部楼层
对楼上的说法,我个人认为可分两步走,一是设一个N=8或9,在N次范围内计算精度满足时退出,二是在N次运算还未达到计算精度时,提示键盘输入N,可多次输入,直到运算结果达到计算精度要求,提示中输入小于“1”的零或负数表示强行结束计算,按计算得出的精度输出结果。这样在调试完后具体运行时既可避免死循环,又可保证计算精度。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-11-12 16:10:04 | 显示全部楼层
圆和弧是可以tan的,spl之类倒是可以考虑此法。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 593个

财富等级: 财运亨通

发表于 2005-11-12 16:34:16 | 显示全部楼层
几何方法还是首选方法

公切线用两次 tan 捕捉即可
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-11-12 16:40:14 | 显示全部楼层
最初由 cy956 发布
[B]圆和弧是可以tan的,spl之类倒是可以考虑此法。 [/B]

我也这样觉得,只是还没想清楚。请斑竹出手吧!!!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 7249个

财富等级: 富甲天下

发表于 2005-11-12 16:59:38 | 显示全部楼层
(setvar "Osmode" 16)
(command "Line" Pause Pause "")
.
.
.
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 6530个

财富等级: 富甲天下

发表于 2005-11-12 17:31:05 | 显示全部楼层
“渐近法”作为一种思路是很好的,但编程时除非不得已不宜使用,不仅效率低,大家所说的“死循环”是最致命的缺点,我们知道,函数是千奇百怪的,判断条件就未必是收敛的,这样的“死循环”在测试时不一定发现,运行时出现可能发生意想不到的错误。与其这样,不如花一点功夫,再把相关“理论”知识温习一下,毕竟“磨刀不误切菜功”吗。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-11-12 20:19:05 | 显示全部楼层
为什么要“舍近求远”?
  1. [FONT=courier new](command "line" "tan" pause "tan" pause "")[/FONT]

根据陈伯雄编著的《Visual LISP程序设计-技巧与范例》P148,似乎并不赞成解析式程序的方法。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-11-12 20:44:47 | 显示全部楼层
八仙过海.只要能解决问题就行.
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-11-12 22:34:30 | 显示全部楼层
初学lsp时抄来的,也从来没用过的程序:

  1. (defun c:gqx(/ en1 e1 b1 r1 c1 en2 e2 b2 r2 c2 g s r3 e3)
  2.   (setq en1(entsel "\n 在切点附近选择第一个圆或弧:")
  3.         e1(osnap (cadr en1) "nea")
  4.         b1 (entget (car en1))
  5.         r1 (dxf 40 b1) c1 (dxf 10 b1)
  6.         en2(entsel "\n 在切点附近选择第二个圆或弧,二者不相切:")
  7.         e2(osnap (cadr en2) "nea")
  8.         b2 (entget (car en2))
  9.         r2 (dxf 40 b2) c2 (dxf 10 b2)
  10.         d(distance c1 c2) )
  11.   (if (< r1 r2)
  12.     (setq g r1 r1 r2 r2 g        
  13.               g c1 c1 c2 c2 g       
  14.               g e1 e1 e2 e2 g))
  15.   (if (< (- r1 r2) d)(progn
  16.     (initget "E I e i")
  17.     (setq s (getkword "\nE 外切/I 内切:<E 外切>" ))
  18.     (mapcar 'setvar '("cmdecho"   )'(0   ))
  19.     (if (or (= s "e")(= s "E")(not s))       
  20.       (setq r3 (- r1 r2)) (setq r3 (+ r2 r1))    );if
  21.     (command "circle" c1 r3)
  22.     (setq e3 (polar c1 (angle c1 e1) r3))
  23.     (command "line" c2 (osnap e3 "tan") "")
  24.     (setq e3 (getvar "LASTPOINT") e1 (polar c1 (angle c1 e3) r1) )
  25.     (repeat 2 (command "erase" "l" ""))
  26.     (command "line" e1 (osnap e2 "tan") "")
  27.     (mapcar 'setvar '("cmdecho"   )'(1   ))
  28.     )
  29.     (prompt "\n...嘿!嘿!嘿! 所选不合要求!!")
  30.   )
  31.   (princ)
  32. )
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-11-12 22:47:41 | 显示全部楼层
最初由 ll_j 发布
[B]“渐近法”作为一种思路是很好的,但编程时除非不得已不宜使用,不仅效率低,大家所说的“死循环”是最致命的缺点,我们知道,函数是千奇百怪的,判断条件就未必是收敛的,这样的“死循环”在测试时不一定发现,运行... [/B]

刚开始我也认为这方法效率会比较低,但就这个程序的情形,发现效率比想象的高很多,通常程序只经过6、7个循环即求出精确的结果。本例至少证明了一点,在某些情形下,这个思路能够以可以接受的效率来解决问题,而编程很简单。这正是有趣的地方。
xyp1964:本程序不是实用程序,只是个验证程序。
实用程序(测试):求两条任意曲线的切线。

  1.   [FONT=courier new]
  2. ;;;&Oacute;&Atilde;&frac12;&yen;&frac12;ü·¨&raquo;&shy;&Aacute;&frac12;&Ocirc;&sup2;/&raquo;&iexcl;&micro;&Auml;&Ccedil;&ETH;&Iuml;&szlig;
  3. ;;;20051111
  4. (defun c:tantan        (/ ANG CEN1 CEN2 ENS1 ENS2 N PT01 PT02 PT1 PT2 PT3 PT4
  5.                  RAD1 RAD2
  6.                 )
  7.   (setq        ens1 (entsel "\n1st arc: ")
  8.         ens2 (entsel "\n2nd arc: ")
  9.   )
  10.   (mapcar 'set '(en1 pt1) ens1)
  11.   (mapcar 'set '(en2 pt2) ens2)
  12.   (setq        pt1 (osnap pt1 "nea")
  13.         pt2 (osnap pt2 "nea")
  14.         n   0
  15.   )
  16.   (while (and (not (equal pt1 pt01 1e-99)) ;&frac12;&yen;&frac12;ü&Ntilde;&shy;&raquo;·
  17.               (not (equal pt2 pt02 1e-99))
  18.               (< n 1000)
  19.          )
  20.     (setq pt01 pt1
  21.           pt02 pt2
  22.           n    (1+ n)
  23.     )
  24.     (command "line" "non" pt1 "tan" pt2 "")
  25.     (setq pt2 (getvar "lastpoint"))
  26.     (command "line" "non" pt2 "tan" pt1 "")
  27.     (setq pt1 (getvar "lastpoint"))
  28.     (repeat 2 (entdel (entlast)))
  29. ;;;    (princ " ")
  30. ;;;    (princ (distance pt01 pt1))
  31. ;;;    (grread)
  32.   )
  33.   (command "line" "non" pt1 "non" pt2 "")
  34.   (princ "\ncount: ")
  35.   (princ n)
  36.   (princ)
  37. )
  38.   [/FONT]
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 3个

财富等级: 恭喜发财

发表于 2005-11-14 00:09:14 | 显示全部楼层
是个值得探讨的问题,特别是对于有些实际问题并不需要有精确的值,因为实际的工作当中也是要有允许的误差的,而且对于一些没有数学模型可以依据的问题更是有价值
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1个

财富等级: 恭喜发财

发表于 2005-11-14 07:33:28 | 显示全部楼层
都是高手,先学习学习。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-11-23 19:51 , Processed in 0.318474 second(s), 59 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表