明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 4238|回复: 7

[【高飞鸟】] 表达式求值

  [复制链接]
发表于 2016-4-18 15:39:57 | 显示全部楼层 |阅读模式
表达式一般来说有三种:前缀表达式、中缀表达式、后缀表达式,其中后缀表达式又叫做逆波兰表达式。中缀表达式是最符合人们思维方式的一种表达式,顾名思义,就是操作符在操作数的中间。而前缀表达式和后缀表达式中操作符分别在操作数的前面和操作数的后面。在写表达式,我们一般用中缀表达式,譬如 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. )

完整代码见附件:

样例:
;;; 例子:
;;; (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-GetInterfaceObject (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上此法行不通,因为不能创建脚本对象。


本帖子中包含更多资源

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

x

评分

参与人数 7明经币 +9 金钱 +160 收起 理由
vectra + 1 很给力!
xshrimp + 2 + 30 神马都是浮云
USER2128 + 1 很给力!
jltx123456 + 1 赞一个!
lucas_3333 + 1 + 50 神马都是浮云
ll_j + 1 + 50 赞一个!
qjchen + 2 + 30 很给力! 谢谢高飞兄分享

查看全部评分

"觉得好,就打赏"
    共1人打赏
发表于 2016-4-24 11:12:48 | 显示全部楼层
uti:bench
子程序呢?
 楼主| 发表于 2016-4-27 11:21:25 | 显示全部楼层
crtrccrt 发表于 2016-4-24 11:12
uti:bench
子程序呢?

uti:bench 是一个测试程序,与本程序无多大关联,只是用于比较几种计算法的速度而已。
发表于 2016-4-27 12:08:23 | 显示全部楼层
我先收藏了,谢谢大师!
发表于 2017-10-6 12:40:42 | 显示全部楼层
感谢 highflybird 大师分享程序!!!!!
发表于 2017-10-12 12:52:12 | 显示全部楼层
没币下载,求2个。
发表于 2018-8-21 19:50:26 | 显示全部楼层
狂顶
用力顶
我用力顶
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-15 01:17 , Processed in 0.456888 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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