2012-03-26 87 views
3

我',嘗試這個簡單的代碼。它示出了第一10個整數,不能在浮法來表示:(浮動)鑄造不起作用

int main(){ 
    int i, cont=0; 
    float f; 
    double di, df; 
    for(i=10000000, f=i; i<INT_MAX; i++, f=i, df=f, di=((float)i)){ 
    if(i!=f){ 
     printf("i=%d f=%.2f df=%.2lf di=%.2lf\n", i, f, df, di); 
     if(cont++==10) return 0; 
    } 
    } 
    return 1; 
} 

是雙變量,但我將其設置爲(浮點)我,所以它應該是等於DF,但不是這樣。

例如,數16777217被表示爲16777216˚FDF,但仍然是16777217,忽略(浮點)鑄造。

這怎麼可能?

**我用這:海灣合作委員會(Ubuntu的4.4.3-4ubuntu5)4.4.3

+1

什麼平臺和編譯器版本? – sarnold 2012-03-26 22:27:29

+3

爲什麼你使用這樣的逗號運算符?絕對沒有必要,並增加了不必要的複雜問題。 – Joe 2012-03-26 22:28:10

+0

你不需要說'%lf'。只是'%f'很好,而且它意味着'double'。 – 2012-03-26 22:29:40

回答

2

有關您的問題是6.3.1.8:2在the C99 standard

浮動的值表達式的操作數和浮點數的結果可以以比該類型所需的 更高的精度和範圍來表示;類型不會因此而改變。

並且特別腳註52:

鑄造和賦值操作符仍然需要如6.3.1.4和6.3.1.5描述,以進行他們的指定的轉換。

閱讀腳註,我會說你已經在編譯器中發現了一個錯誤。

您可能已經在您的編譯器中發現了兩個錯誤:i!=f比較在浮動塊之間完成(請參閱標準的同一頁上的促銷規則),所以它應始終爲false。儘管在後一種情況下,我認爲編譯器可能允許使用更大的類型進行6.3.1.8:2的比較,可能會使得比較等效於(double)i!=(double)f,因此有時也是如此。段6.3.1.8:2是我最討厭的標準中的段落,我仍然試圖理解嚴格的別名。

+0

非常感謝。我認爲你是對的,並且在編譯器中存在一個bug(或特徵?),因爲我!= f在雙精度而不是浮點數之間進行比較。 – salteador 2012-03-26 23:11:32

+0

這是gcc中一個非常長期的已知bug,開發人員幾乎無法解決,因爲它會適度地損害不關心正確性的人的性能。如果你不關心讓你的程序與舊的cpus不兼容,你可以用'-msse'來解決這個問題(使用SSE而不是FPU作爲浮點)。請注意,在x86以外的平臺(也許是m68k?)上,這個問題不存在。 – 2012-03-27 03:07:51

+0

@R:如果他們想要最大化性能而不考慮正確性,爲什麼不簡單地讓所有的浮點運算返回42.0?這不會比假裝對他們做數學運算快嗎?對於編譯器來說,使用'f4 = f1 + f2 + f3;'對於中間值使用80位擴展格式而不是32位格式是很好的恕我直言,*假如它在處理這些事情時是一致的,但如果比較和演員沒有完成適當的類型,他們是無意義的,「速度」是無關緊要的。 – supercat 2013-09-23 22:11:16

2

這篇文章解釋了這是怎麼回事:

http://www.exploringbinary.com/when-floats-dont-behave-like-floats/

基本上額外的精度可能會被保存在機器的不同表達的評價上,使這將是平等的花車不相等。

+0

非常感謝。我不知道;) – salteador 2012-03-26 23:12:50

+0

該標準要求演員丟棄任何額外的精度。海灣合作委員會在這方面只是被打破,這是一個已知的問題。這個問題可以通過'-ffloat-store'選項來部分支持,但是這隻能解決分配問題,而不能解決問題。 – 2012-03-27 03:05:23