2013-11-15 27 views
0

我有這個循環這應該迭代lx倍超過x(範圍[-1,1])和ly倍y(範圍[-1,1]),9倍總共,但它重複了16次!爲什麼是這樣??浮點循環運行更多的迭代比應該

#include <stdio.h> 

int main(void) { 
    double lx=3,ly=3; 
    double du = (1-(-1))/double(lx); 
    double dv = (1-(-1))/double(ly); 
    int count=0; 

    for (double y=-1; y < 1; y += dv) 
    for (double x=-1; x < 1; x += du) { 

     count++; 
    } 

    printf("\n\n%d lss\n", count); 
} 
+5

因爲浮點運算不準確。你得到一個值(例如)y = 0.99999999999999,所以y <1是真的,並且你的循環執行了太多次。 – john

+0

它不能那麼不準確!我沒有在這裏處理無窮小數量。有趣的是,如果我設置lx = ly = 4,循環仍然運行4x4 = 16次! – Suffern

+0

@Suffem:是的,它可能是不準確的。當你用二進制浮點計算'2./3'時,**結果不是2/3 **。它稍微少一些,這就是所有需要使'y'的值略小於1的地方,你可能預期爲1. –

回答

3

認真嗎?

您正在迭代[-1,-1/3,1/3,1]。

你可以通過看到這個在循環中放置一個輸出語句來看看發生了什麼。

-1

您需要以不同的方式計算開始點和結束點之間的差異,因爲您在此處使用雙打。

因此,而不是end - start使用end - start + 1.0,你就完成了。

+0

這個工程,但爲什麼? – Suffern

+0

因爲當你指定一個整數範圍像[-1,1 [你只有2個數字之間,但有雙打你有更多,因爲0。9999999也適合那裏。所以你必須使間隔增大一個單位以達到真正的寬度。 – Neet

0

我假設你的C實現使用IEEE-754 64位二進制浮點數爲double,這是最常見的選擇。

每個數字算術系統都是不精確的,所以您使用的數字與精確數學中得到的數字不同。

聲明double du = (1-(-1))/double(lx);dudouble值最接近的2/3,這是0.66666666666666662965923251249478198587894439697265625。

在外循環的第一次迭代中,y爲-1。當du被添加到它在每次迭代結束時,結果是:

  • -0.33333333333333337034076748750521801412105560302734375,
  • 0.3333333333333332593184650249895639717578887939453125,和
  • 0.99999999999999988897769753748434595763683319091796875。

顯然,y的最後一個值小於1,所以循環繼續進行另一次迭代。

循環迭代器通常應該使用整數值,這樣很容易確保使用精確的算術。您可以縮放迭代器以產生其他所需的值:

for (int iy = 0; iy < 4; ++iy) 
{ 
    double y = iy * 2/3. - 1; 
    … 
}