cfi*_*cfi 4 floating-point expression tcl
由于浮点数的内部表示而知道不准确(请参阅维基百科,搜索到:"使用相等测试"......),在执行时仍然会出现意外情况:
% expr int(0.57 * 10000)
5699
% expr int([expr 0.57 * 10000])
5700
Run Code Online (Sandbox Code Playgroud)
是否嵌套expr
禁止?为什么它会改变通过的浮点值?或者它是否会改变浮点运算的顺序,那些影响结果的是什么?
更新:有关比较浮点数与速度(和次要链接),一些基础知识而不是基础知识以及IEEE 754-2008标准描述的主题.
这是一个有趣的问题,因为它涉及一些微妙的事情.
% expr int(0.57 * 10000)
5699
Run Code Online (Sandbox Code Playgroud)
这段代码(没有替换,所以它的工作"不出所料")表明浮点数本身就是令人惊讶的事情.特别是,0.57没有精确的表示形式作为IEEE双精度浮点数(它是base-2); 事实上,它的表示略低于0.57,所以当向下舍入时(这就是int(...)
10000本身就是准确的)你会下降到5699.你会看到与其他语言相同的行为.
% expr int([expr 0.57 * 10000])
5700
Run Code Online (Sandbox Code Playgroud)
现在这个特别有趣.你首先看到内部计算正在完成,结果浮点数转换为字符串(因为没有其他方法可以做到).现在,您必须使用Tcl 8.4(或之前),其中默认数字呈现规则(实际上)通过打印数字的前15位有效数字得到的结果; 在这种情况下,给你5700.00000000000
(好吧,在右边有一些零截断),然后从头开始重新解释为首先是一个双精度(正好是5700.0),然后转换为5700.
数字转换规则在Tcl 8.5中已更改.如今,当Tcl将浮点数转换为字符串时,它会产生最短的字符串,该字符串将转换回完全相同的浮点数(即,通过字符串的边的行程将在得到的double中给出相同的位模式).这意味着你现在从来没有看到上述两件事之间的差异.(如果你真的想强制使用固定数量的小数位,请使用format %.15g [expr 0.57 * 10000]
.)
如果你正确地表达你的表达,你也不会观察到8.0到8.4的行为,因为社区已经建议人们做了十多年:
$ tclsh8.4
% expr {int([expr 0.57 * 10000])}
5699
Run Code Online (Sandbox Code Playgroud)
那是因为这不会强制将内部expr
调用的结果解释为字符串.(它也更快更安全.)