9

所以我有一個功能,看起來是這樣的:cout可以以某種方式改變變量嗎?

float function(){ 
    float x = SomeValue; 
    return x/SomeOtherValue; 
} 

在某些時候,這個功能溢出,並返回一個非常大的負值。嘗試追查正是這個是怎麼回事,我添加了一個COUT語句,因此該函數是這樣的:

float function(){ 
    float x = SomeValue; 
    cout << x; 
    return x/SomeOtherValue; 
} 

和它的工作!當然,我通過使用雙重解決了這個問題。但我很好奇,爲什麼這個功能在我打開它時正常工作。這是典型的,還是可能在我失蹤的其他地方存在一個錯誤?

(如果它的任何幫助,存儲在浮動值僅僅是一個整數值,並沒有特別大的一個,我只是把它放在一個浮動,以避免鑄造。)

回答

18

歡迎來到浮點的美妙世界。你得到的答案可能取決於你編譯代碼的浮點模型。

發生這種情況是因爲IEEE規範與運行代碼的硬件之間的差異。你的CPU可能有80位浮點寄存器,用來保存32位浮點值。這意味着當值被強制寫入內存地址時(也稱爲「歸位」寄存器),值保留在寄存器中的精度要高得多。

當您將值傳遞給cout時,編譯器必須將浮點寫入內存,這會導致WRT溢出情況的精度和有趣行爲丟失。

請參閱VC++ floating point switches上的MSDN文檔。您可以嘗試使用/ fp:strict編譯並查看會發生什麼。

+0

這裏還有一個GCC說明http://gcc.gnu.org/wiki/x87note 由於這個奇妙的行爲,除非使用預先計算的值,否則比較浮點計算也是固有的破壞。 – hazzen 2008-09-08 19:57:12

3

打印值來清點不應該以任何方式改變參數的值。

但是,我看到了類似的行爲,添加調試語句導致值的變化。在這些情況下,也可能是這個,以及我的猜測是附加語句導致編譯器的優化器行爲不同,因此爲您的函數生成不同的代碼。

添加cout語句意味着直接使用x的vaue。如果沒有它,優化器可能會刪除該變量,因此更改計算順序並因此更改答案。

0

我不認爲cout對變量有任何影響,問題將不得不在其他地方。

2

順便說一句,它總是一個好主意,用const聲明一成不變的變量:

float function(){ 
    const float x = SomeValue; 
    cout << x; 
    return x/SomeOtherValue; 
} 

除其他事項外,這將阻止您無意通過你的變量函數,可以通過非const引用對其進行修改。

1

cout導致對變量的引用,這通常會導致編譯器強制它將其泄漏到堆棧。

因爲它是一個浮點數,所以這可能會導致它的值從它通常具有的double或long double表示中截斷。

調用任何函數(非內聯)需要一個指針或引用x應該最終導致相同的行爲,但如果編譯器後來變得更聰明,學會內聯它,你將同樣擰緊:)

相關問題