這是一個有趣的問題,因爲它觸及了一些微妙的事情。
% 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