2011-08-28 171 views
3

我想就一些建議如何優化while循環如下:浮點比較

double minor_interval = 0.1; 
double major_interval = 1.0; 

double start   = 0.0; 
double finish   = 10.0; 

printf("Start\r\n"); 

while (start < finish) 
{ 
    printf("Minor interval: %.20f\r\n", start); 

    double m = fmod(start, major_interval); 
    printf("m: %.20f\r\n", m); 

    if (m == 0) 
     printf("At major interval: %.20f\r\n", start); 

    start += minor_interval; 
} 

printf("Finished\r\n"); 

從本質上講,我在環由微小的間隔遞增計數器,想如果我處於主要區間,則每次都知道循環。把它畫成毫米間隔的標尺,每當我到一個主要的間隔時,我想畫一釐米。鑑於浮點運算的不準確性,我如何修改上述循環來實現我需要的功能?我嘗試了使用容差比較模數結果的不同方法,但沒有運氣。請注意,次要間隔和主要間隔可以是任何值,即小數= 0.4和大數= 1.6(以畫四分之一英里增量)。

在此先感謝。

+0

如果您的號碼是唯一正確的,以2小數點,你爲什麼不乘以100的所有號碼,去了很精確的整數算術? 對於整數,[div](http://www.cplusplus.com/reference/clibrary/cstdlib/div/)或[ldiv](http://www.cplusplus.com/reference/clibrary/cstdlib/ldiv/ )。 –

+0

@Ron英寸秤通常會有1/8或0.125的增量。爲什麼在解決不完美的解決方案時很容易避免像你所建議的那樣限制。 –

+0

@大衛我避免了浮點運算,除非無法避免,或者在整數運算中實現效率很高。我只是建議數字是否限制在2位小數,但如果情況並非如此,我肯定會選擇你的解決方案(我把你的答案投給了:))。 –

回答

6

我會用一個for循環來實現這個變量int變量i。使用整數避免了由於浮點運算的限制而導致的舍入問題。 [見What Every Computer Scientist Should Know About Floating-Point Arithmetic。]

讓從0i運行到iFinish-1並設置time等於start + i*minor_intervaliFinish的值可以通過將(finish-start)/minor_interval四捨五入到最近的整數來找到。

主軸更新可以用類似的方式處理。回合major_interval/minor_interval至最近的int,比如k。然後在每次第k次迭代中更新主軸標記。

在代碼方面,它看起來是這樣的:

double round(double r) { 
    return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); 
} 
... 
int iFinish = round((finish-start)/minor_interval); 
int k = round(major_interval/minor_interval); 
for (int i=0; i<iFinish; i++) 
{ 
    double time = start + i*minor_interval; 
    bool isMajor = (i%k == 0); 
    ... 
} 
0

爲什麼你的寬容的方法不起作用的原因是,它只佔時保存的值略高於它應該是。 (例如,當它是1.0001,而不是1,如果是0.999,而不是1,你的方法是行不通的)

爲了解決這個問題,檢查它是否在預期值的側的公差範圍內。

因此,而不是:

if (m == 0) 

使用:

if (m < small_value || major_interval - m < small_value) 

其中small_value是一樣的東西1E-8。

0

我會讓循環成爲使用整數的for循環。另外,由於這些tyes數字的不穩定性質,您應該避免使用==運算符。

所以對雙打轉換成整數的循環的目的:

numIntervals = (int)((finish - start)/minor_intervals); 
majIntervalsGap = numIntervals/(int)((finish - start)/major_intervals); 
double time = start; 
for (int loop = 0;; loop < numIntervals; ++loop) 
{ 
    bool isMajor = ((loop % majIntervalsGap) == 0); 

    ... do you ourput here as you have the desired info for it 
    time += minor_interval; 
} 
+0

(int)演員如何處理四捨五入?我相當肯定,它不會繞到最近,這是這裏所需要的。 –