TCL脚本语言-4-数学计算,怎么这么烦
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数学计算,怎么这么烦?
前面的快速入门教程里面已经提到了expr命令,TCL中所有的数学计算都是通过expr 命令来完成的。这一点和其他语言非常的不同,例如Python中:
>>> from math import *
>>> pi
3.1415926535897931
>>> print cos(pi/4)*2 , sqrt(2)
1.41421356237 1.41421356237
>>>
Python里面的表达式是非常直观的,其他语言例如VBScript等也是如此。但是TCL中,即使是计算两个数字相加,都得使用expr命令:
set a 100; set b 200
puts “a+b = $a+$b”;#输出a+b = 100+200
puts “a+b = [expr $a+$b]”;#输出a+b = 300
TCL中,expr加上一堆的$符号,方括号等字符,最简单的表达式,看起来都是非常不爽。这对于刚刚接触TCL的人来说,简直是一件无法忍受的事情,当初我也是这么认为的。后来在网上发现有人还真的通过扩展,在TCL实现类似Python的语法,比如原来的:
set a [expr $a+$b]
可以写成:
a = $a+$b
至于是怎么实现的,我们后面会进行详细的分析。但是我觉得,既然选择了TCL,就要习惯其用法;要么当初就选择Python拉到,所以我不赞成上面的这种改进。而且习惯了TCL 之后,也没有觉得它没有我们想象中的那么不方便。
语法描述
expr命令是TCL的核心命令之一,其语法格如下:
expr arg ?arg arg ...?
该命令可以有一个或者多个参数,在执行的时候,把所有的参数连接起来成为一个数学
表达式字符串,然后计算这个表达式,计算结果作为命令结果返回。下面两条命令写法不一样,但是结果一样:
set PI 3.1415926535897932
set sqrt2_1 [expr "cos($PI/4)*2"]
set sqrt2_2 [expr cos ( $PI / 4 ) * 2]
puts "sqrt2_1 = $sqrt2_1\nsqrt2_2 = $sqrt2_2"
两个expr命令,第一个命令只有一个参数(所有的东西都被引号括起来),第二个则拆开了,参数个数一堆。但是计算结果都是一样的:
sqrt2_1 = 1.41421356237
sqrt2_2 = 1.41421356237
操作符
expr命令所支持的计算操作符是C语言中操作符的一个子集。并且写法和优先级也和C 语言完全一致。除了数学计算操作符之外,expr还支持字符串的比较操作。下面是expr支持的操作符,按照优先级从高到低排列:
操作符含义说明
- + ~ !单目取负;单目正号;按位取反(not);逻辑取反;
* / %乘法;除法;取余;
+ -加法;减法;
<< >>向左移位,向右移位;
< > <= >=比较操作符,小于、大于、小于等于、大于等于;结果1表示true,0表示false;这几个操作符可以作用于字符串,进行大小写敏感的比较;
== !=比较是否相等:等于、不等于;结果1和0分别表示true和false。可以作用于所有类型的操作数;
eq ne 字符串的比较:等于、不等于;结果1和0表示true和false。进行计算的时候,其操作数都被当成字符串进行比较。
&按位与操作(AND),只能够作用于整数;^按位异或操作(XOR),只能构作用于整数;|按位或操作(OR),只能构作用于整数;
&& 逻辑与操作(AND),只有两个操作数都非零的时候,结果才是1,否则为0。只能够作用于boolean类型或者数字类型。
||逻辑或操作(OR),只有两个操作数都为0的时候,结果才是0,否则为1;只能够作用于boolean或者数字类型。
x?y:z If-then-else操作,和C中的比较类似。如果x计算得出非零值,那么y的值就
是表达式的结果;否则,z的值就是表达式的结果。x的值必须是一个数值或者
boolean值。
其中,&&,||,x?y:z三个操作符和C语言中一样,会进行布尔短路计算:当表达式计算了一部分就知道整个结果的时候,那么其他部分就不会计算了。例如:
proc a { t } {
puts "PROC A . t=$t"
return [expr $t+1]
}
puts [expr {[a 100]>100 ? [a 200] : [a 300]}]
上面的代码执行输出为:
PROC A . t=100
PROC A . t=200
201
可以看到,[a 300]根本就不会执行。但是如果这样写:
puts [expr “[a 100]>100 ? [a 200] : [a 300]”]
把expr后面得表达式用双引号括起来,结果就不一样了,a命令会执行三次!为什么,大家都是高手,自己分析。
操作数
数学表达式中肯定离不开操作数,操作数是操作符进行运算的对象(这简直是废话)。expr命令在解析操作数的时候,依照如下顺序进行:
1.整数。expr首先判断是否是整数,expr表达式中的整数可以表示成普通的十进制,
也可以表示成8进制(用0开始)和十六进制(用0x开始)。
2.浮点数。如果操作数不具备上面描述的整数的格式,那么就试图将其解释成浮点数。
expr表达式中的浮点数和ANSI-C中的浮点数格式类似,后面不能够加上f,F,L,l这
样的后缀,例如2.1,3.,3.2E1.0等都是正确的浮点数。
3.字符串。如果既不能够解释成整数,也不能够解释成浮点数,那么就只有当成字符
串了。
使用整数注意范围,8.4版本的TCL中,整数的最大范围是0x7FFFFFFFFFFFFFFF,也就是说,使用8个字节来表示的。但是8.3版本的TCL中,整数是32个字节来表示。
expr的操作数可以是如下的形式:
1.一个数值;
2.$varName格式的变量引用;