这是一个有趣的问题,因为它触及了一些微妙的事情。
% expr int(0.57 * 10000)
5699
此代码(有没有换人,所以它的工作原理“意料之中”)显示,浮点数,本身就是令人惊奇的事情。特别是,0.57没有精确的表示形式作为IEEE双精度浮点数(基数为2);实际上,它的表示比精确到0.57稍低,所以当向下舍入时(这是int(...)
所做的; 10000本身就是确切的),您可以下降到5699.您也会看到与其他语言相同的行为。
% expr int([expr 0.57 * 10000])
5700
现在这特别有趣。你首先看到内部计算正在完成,并且生成的float被转换为一个字符串(因为实际上没有其他方法可以做到这一点)。现在,您必须使用Tcl 8.4(或之前),默认数字渲染规则是(实际上)通过打印数字的前15个有效数字而得到的;在这种情况下,让你5700.00000000000
(当然,在右边零的一些截断),这就是再从头作为第一重新演绎双(准确5700.0),然后是会转换为5700
的数量规则转换在Tcl 8.5中改变。现在,当Tcl将浮点数转换为字符串时,它会产生最短的字符串,该字符串将转换回完全相同的浮点数(即通过字符串域的旁路将在所得到的双精度中给出相同的位模式)。这意味着你现在从来没有看到上述两件事之间的区别。 (如果你真的想要强制固定的小数位数,请使用format %.15g [expr 0.57 * 10000]
。)
如果你正确地使用表达式,就像社区建议人们做的那样,你也不会观察到8.0到8.4的行为十多年来:
$ tclsh8.4
% expr {int([expr 0.57 * 10000])}
5699
这是因为这并不强制内部expr
调用的结果被解释为一个字符串。 (它也更快,更安全。)
感谢您确认怀疑并添加了大量的知识。而且,是的,如果我有一个tcl8.4标签,Sherlock ;-) – cfi 2012-03-28 10:57:08