2016-04-19 42 views
-1

優化循環我需要執行一個循環通過使用浮點值作爲循環計數器

while (X) do Y 

上N倍,這是一個很大的數字。雖然循環體Y是相當快的,但測試X佔用了運行時間的大約70%。

我可以事先計算循環迭代次數N,所以不是使用X作爲條件,而是可以使用簡單的For-Loop。

for (i=1 to N) do Y 

但是,N可能會超過整數可存儲在機器上的最大值,所以這不是一個選項。作爲替代,我建議使用浮點變量F.隨着N大,很可能是F能夠不完全等於N.因此,我計算F到成爲最大的浮點數小於N.這讓我跑

for (i=1 to F) do Y 
while (X) do Y 

大多數迭代會每次不需要測試X,只需要最後一個NF。

問題是:我將如何實現for-Loop從1到F?簡單地增加計數器或在每一步中將F減1將不起作用,因爲數值誤差會變得太大。我目前的解決方案是:

for (while F > MAXINT) 
    for (i=1 to MAXINT) 
     do Y 
    F -= MAXINT 
while (X) do Y 

有沒有更好的方法來解決這個問題?

回答

0

你是什麼意思的數值錯誤?浮點計數在其精確度內是精確的。 下面是通過使用正好以下數據類型整數表示的最大值:

uint32max  = 4294967295 
uint64max  = 18446744073709551615 
float32intmax = 16777216 
float64intmax = 9007199254740992 

從0增加到最大的每一個整數是沒有數值誤差精確表示。

正如您所看到的,最大的計數可用於uint64。接下來是float64,然後是uint32,最後是float32。

當你遞增uint32 = 4294967295時會發生什麼? 0.

當你增加float32 = 16777216會發生什麼? 16777216.

哪個更好?

你有沒有想過使用二維循環?如果N是一維環路的最大數量,那麼N×N是二維環路的最大值等等,這樣如果最大計數小於MAXUINT×MAXUINT,則將N分解爲:

N == M * MAXUINT + R; 

其中

M = N/MAXUINT; 
R = N - M * MAXUINT; 

然後

for (i = M; i--;) for (j = MAXUINT; j--;) DoStuff(); 
for (i = R; i--;) DoStuff(); 

如果MAXUINT * MAXUINT是不是足夠大的指望你,你可以添加3-,4-維...循環。

+0

你所描述的只是浮點數的一個子集,如你所示,它包含的數字比整數數據類型少。我正在談論整個32位浮點數。關於二維循環,不能保證我的數字N是一個正方形整數。 –

+1

你可以使用nextafter()和浮點數來訪問所有的數字,但是這與相同長度的整數相同。我認爲你期望浮點數比現在更多。 –

+0

@像素是正確的。 FP範圍內的每個整數都精確表示(從0開始),「f = f + 1.0」操作對於「真實」操作精確地爲1,677,7216次,對於雙倍操作而言爲9,007,199,254,740,992次。但是什麼樣的系統有'double'但是沒有64位int? – DigitalRoss