C 漂浮死迴圈

2021-07-24 02:37:53 字數 2585 閱讀 4430

由於碰到for迴圈陷入死迴圈問題,所以查了一下,主要是儲存方式的問題,所以為了避免死迴圈,使用int或者是較小的float。

**:在c#(.net 3.5 sp1)下面的**是我的機器上乙個無限迴圈:

for (float i = 0; i < float.maxvalue; i++) ;

它達到了數16777216.0和16777216.0 + 1的結果為16777216.0。 然而在這一點上:i + 1的=島

這是一些瘋狂。

我知道有如何浮點數儲存一些誤差。 我讀過整數更大的2 ^ 24比不能正確地儲存為浮動。

不過上面的**,應該在c#有效的,即使在一些不能正確代表。

為什麼它不工作?

你可以得到相同的情況發生,以雙倍的,但它需要乙個很長的時間。 9007199254740992.0是極限了一倍。

--------------解決方案-------------

右,所以問題是,為了新增乙個到浮子,那就要成為

16777217.0 

它只是恰巧,這是在為基數的邊界,不能完全作為乙個float表示。 (可接下來的最高值是16777218.0

因此,其四捨五入為最接近的可表示浮點數

16777216.0 

讓我這樣說:

既然你有精確的浮動金額,必須由更高和-較大的數字遞增了。

好吧,這是乙個有點難以解釋,但試試這個:

float f = float.maxvalue; 

f -= 1.0f; 

debug.assert(f == float.maxvalue); 

這將執行得很好,因為在那個值,為了表示1.0f的差異,就需要超過128位的精度。 浮子只有32位。

edit2

根據我的計算,至少128個無符號二進位制數字是必要的。

log(3.40282347e+38) * log(10) / log(2) = 128 

作為解決你的問題,你可以通過兩個128位的數字迴圈。 但是,這至少需要十年才能完成。

想象一下,例如,乙個浮點數由最多2顯著十進位制數字表示,再加上乙個指數:在這種情況下,你可以指望從0到99完全相同。 接下來將是100,而是因為你只能有乙個將被儲存為「1.0倍10到2的冪」2顯著數字。 加一那會是......什麼?

在最好的,這將是101作為中間結果,這實際上將被儲存(通過捨入誤差而丟棄微不足道第三位)為「1.0倍至10的2的冪」一次。

要了解什麼錯你將不得不讀浮點的ieee標準

讓我們來看看的第二個浮點數的結構:

浮點數被分為兩個部分(ok 3,卻忽略了符號位為秒)。

你有乙個指數和乙個尾數。 像這樣:

smmmmmmmmeeeeeee 

注意:這不是acurate的位元數,但它給你發生了什麼的總體思路。

要弄清楚什麼號碼,你有我們做如下的計算:

mmmmmm * 2^(eeeeee) * (-1)^s 

那麼,什麼是float.maxvalue將是? 那麼你將有最大可能的尾數和盡可能大的指數。 讓我們假設這看起來是這樣的:

01111111111111111 

在現實中我們定義楠+-inf和幾個其他公約,卻忽略了他們的第二個,因為他們沒有相關的你的問題。

所以,當你發生了什麼9.9999*2^99 + 1好了,你沒有足夠的顯著的數字加1。結果它被四捨五入到相同的號碼。 在單浮點精度的情況下的點+1開始得到捨去恰好是16777216.0

它無關溢,或正在接近最大值。 為16777216.0的浮點值有16777216的二進位制表示您然後加1,所以它應該是16777217.0,不同之處在於16777217.0二進位制表示是16777216! 因此,它實際上並沒有得到增加,或者至少在增量不去做你所期望的。

這是寫的喬恩斯基特一類說明了這一點:

doubleconverter.cs

試試這個**是:

double d1 = 16777217.0; 

console.writeline(doubleconverter.toexactstring(d1));

float f1 = 16777216.0f; 

console.writeline(doubleconverter.toexactstring(f1));

float f2 = 16777217.0f; 

console.writeline(doubleconverter.toexactstring(f2)); 

請注意的16777216.0的內部表示相同16777217.0!

當我接近float.maxvalue的迭代有我只是低於此值。 在下一次迭代增加為i,但它不能保持大於float.maxvalue更大一些。 因此,保持乙個值要小得多,並且再次開始迴圈。

shell 死迴圈if判斷 shell 死迴圈

例1 執行指令碼後會自動載入firefox瀏覽器,並開啟指定網頁。如果使用者關閉firefox,指令碼會再次自動重新開啟firefox。如需結束迴圈,中止t2.sh程序即可。注意不要同時執行兩個t1.sh指令碼,否則 若事先不知道指令碼名,也可以通過類似於 pstree grep firefox 的...

C語言死迴圈,「貪心法」

死迴圈問題例項 int i int a n for i 0 i n i 根據編譯軟體的不同,這段 出現的問題也有不同,一般如果出現錯誤,原因如下 以上這段 編譯器給變數分配記憶體時變數i的記憶體會在陣列a n 的後邊,迴圈內給陣列內的變數賦值是從前往後寫入位址的,當i n時已經寫到編譯器給i分配的那...

c 位址越界,死迴圈初探

1 intmain 210 printf i x n i 11return0 12 執行結果 a 0 19392bf0 a 1 19392bf4 a 2 19392bf8 a 3 19392bfc a 4 19392c00 a 5 19392c04 a 6 19392c08 a 7 19392c0c...