找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 2260|回复: 5

[飞鸟集] 表达式求值

[复制链接]

已领礼包: 8121个

财富等级: 富甲天下

发表于 2016-4-18 15:55:41 | 显示全部楼层 |阅读模式

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

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

×
表达式一般来说有三种:前缀表达式、中缀表达式、后缀表达式,其中后缀表达式又叫做逆波兰表达式。中缀表达式是最符合人们思维方式的一种表达式,顾名思义,就是操作符在操作数的中间。而前缀表达式和后缀表达式中操作符分别在操作数的前面和操作数的后面。在写表达式,我们一般用中缀表达式,譬如 1+2*3-4/5。并且按照操作符的优先级进行计算。
然而LISP语言是一种前缀表达式,为了把表达式转为LISP函数或者求值,需要进行翻译,添加大量的括号和修改函数的顺序。
这个程序的目的就是使得这一工作变简单。
当然,CAD里面本身也有几种种方式能完成这个,但它们的优缺点容我后面讨论。
程序借鉴了飞诗的一些代码,在此深表感谢。
程序的核心代码如下:
  1. (defun CAL:Operators (lst funs Recursive / fun L n)
  2.   (foreach a lst
  3.     (if    (listp a)
  4.       (setq a (CAL:Operators a funs T))                ;如果元素为表,则递归进去
  5.     )
  6.     (if    (setq fun (cdr (assoc (car L) funs)))                   ;前一个符号为+-*/%^运算符
  7.       (if (or (null (setq n (cadr L)))                          ;前前一个符号为空
  8.           (and (VL-SYMBOLP n) (CAL:IsFunction n))           ;或者是函数符号
  9.       )
  10.     (setq L (cons (list fun a) (cdr L)))                    ;无须交换位置
  11.     (setq L (cons (list fun n a) (cddr L)))                    ;交换运算符和操作数位置
  12.       )
  13.       (setq L (cons a L))                                       ;**的不做改变
  14.     )                                            
  15.   )
  16.   (setq n (car L))
  17.   (if (and Recursive (not (cadr L)) (or (listp n) (numberp n))) ;如果是递归的,而且只有一个元素,且这个元素为表或者数字
  18.     n                                ;那么就只取这个元素,以防止多余括号出现
  19.     (reverse L)                            ;cons运算后的反转表列
  20.   )
  21. )


完整代码见附件:
请点击此处下载

请先注册会员后在进行下载

已注册会员,请先登录后下载

文件名称:mycal.lsp 
下载次数:34  文件大小:11.61 KB  售价:5D豆 [记录]
下载权限: 不限 以上  [免费赚D豆]


样例:
;;; 例子:
;;; (CAL:Separate "(sin(-x)-cos(-x+(1+8*(2/7))+2^4-5))*0.5-0.5e-20+20*cos(x)+20")
;;; 结果: ((SIN - X) - (COS - X + (1 + 8 * (2 / 7)) + 2 ^ 4 - 5))
;;; (CAL:Expr2Func "(sin(+x)-cos(-x+(1+8*(2/7))+(2^4)-5))*0.5-0.5e-20+20*cos(x)+20" 'test '(x))
;;; 结果: 定义了一个名为test的函数,参数符号为x
;;; (CAL:Expr2Value "(sin(+0.5)-cos(-pi+(1+8*(2/7))+(2^4)-5))*0.5-0.5e-20+20*cos(pi/2)+20")
;;; 结果: 20.6616

讨论:
;;; 以下是关于这个程序的**方法:
;;; 方法一:用cal函数计算
;;; 如:(cal "1+4+5*2+(5+5)/2+((6+6)/2+(5+5)/2)")
;;; 优点:CAD内置函数。
;;; 缺点:这个函数要求先要加载cal函数.并且三角函数会自动把变量或者数值理解为角度。
;;; 方法二:wcs脚本语言法,无痕提出的一种方法
;;; (setq wcs (vla-GetInte**ceObject (vlax-get-acad-object) "ScriptControl"))
;;; (vlax-put-property wcs "language" "vbs")
;;; (vla-eval wcs "1+4+5*2+(5+5)/2+((6+6)/2+(5+5)/2)")  ;返回 ->31.0
;;; 优点:能按照vb的语法直接计算。
;;; 缺点:难以定义表达式为函数,不能利用自定义函数,在64位CAD上此法行不通,因为不能创建脚本对象。

评分

参与人数 1D豆 +5 收起 理由
/db_自贡黄明儒_ + 5 很给力!经验;技术要点;资料分享奖!

查看全部评分

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

已领礼包: 8121个

财富等级: 富甲天下

 楼主| 发表于 2016-4-18 15:58:28 | 显示全部楼层
附件里面还有几个小小的程序,演示了如何运用。

点评

大师出山了,学习。  详情 回复 发表于 2016-4-18 16:08
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 19个

财富等级: 恭喜发财

发表于 2016-4-18 16:08:26 | 显示全部楼层
Highflybird 发表于 2016-4-18 15:58
附件里面还有几个小小的程序,演示了如何运用。

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

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

发表于 2016-4-18 19:23:53 | 显示全部楼层
以前老大发过一个函数,见 http://bbs.xdcad.net/thread-676357-1-1.html

使用了VBSCRIPT算表达式

点评

这个就是我在讨论里面提及到的方法二。 对于64位的CAD,这个方法无效。  详情 回复 发表于 2016-4-18 20:06
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 8121个

财富等级: 富甲天下

 楼主| 发表于 2016-4-18 20:06:04 | 显示全部楼层
newer 发表于 2016-4-18 19:23
以前老大发过一个函数,见 http://bbs.xdcad.net/thread-676357-1-1.html

使用了VBSCRIPT算表达式

这个就是我在讨论里面提及到的方法二。
对于64位的CAD,这个方法无效。

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

使用道具 举报

已领礼包: 5586个

财富等级: 富甲天下

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-27 06:34 , Processed in 0.382906 second(s), 44 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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