2011-03-14 42 views
1

我在尋找最簡潔和一般的實現以下功能:最簡潔的實現與環繞溢出浮點約束功能的

float Constrain(float value, float min, float max); 

凡約束()範圍內的[min, float)界定value 。即,範圍包括最小值,但不包括maxvalues大於max或小於min環繞一圈。也就是說,以類似的方式整數溢出/下溢。

功能應通過以下測試:

Constrain( 0.0, 0.0, 10.0) == 0.0 
Constrain(10.0, 0.0, 10.0) == 0.0 
Constrain( 5.0, 0.0, 10.0) == 5.0 
Constrain(15.0, 0.0, 10.0) == 5.0 
Constrain(-1.0, 0.0, 10.0) == 9.0 
Constrain(-15.0, 0.0, 10.0) == 5.0 

Constrain( 0.0, -5.0, 5.0) == 0.0 
Constrain( 5.0, -5.0, 5.0) == -5.0 
Constrain( 0.0, -5.0, 5.0) == 0.0 
Constrain(10.0, -5.0, 5.0) == 0.0  
Constrain(-6.0, -5.0, 5.0) == 4.0 
Constrain(-10.0, -5.0, 5.0) == 0.0 
Constrain(24.0, -5.0, 5.0) == 4.0 

Constrain( 0.0, -5.0, 0.0) == -5.0 
Constrain( 5.0, -5.0, 0.0) == -5.0 
Constrain(10.0, -5.0, 0.0) == -5.0 
Constrain(-3.0, -5.0, 0.0) == -3.0  
Constrain(-6.0, -5.0, 0.0) == -1.0 
Constrain(-10.0, -5.0, 0.0) == -5.0 

注意,min PARAM可以被認爲是總數值小於max

有可能是一個非常簡單的公式來解決這個問題,但我是驚人的愚蠢不知道它的廣義解決方案。

回答

2

你是差不多尋找fmod函數。 fmod(x,y)返回xy,餘數爲double s。結果的符號與x相同(等價地,相應的整數部分函數是向零舍入的那個函數),這就是爲什麼它只有差不多你想要的。所以,如果x>=lo然後lo+fmod(x-lo,hi-lo)是正確的事情,但如果x<lo然後hi+fmod(x-lo,hi-lo)是哦,所以,幾乎是正確的事,只是當x<lo其結果可能是要麼lohihi而不是lo

所以。您可以分成三部分:

double Constrain(x,lo,hi) { 
    double t = fmod(x-lo,hi-lo); 
    return t<0 ? t+hi : t+lo; 
} 

,或者您可以使用floor而非[編輯,因爲這樣做的第一個版本是不是我的意思可言]:

double Constrain(x,lo,hi) { 
    double t = (x-lo)/(hi-lo); 
    return lo + (hi-lo) * (t-floor(t)); 
} 

隨你挑,如果你關心是可理解的;如果你關心的是性能,就試試它們。

+0

幾乎FMOD(和fmodf)確實。但不完全。這就是我的目標。我認爲我最喜歡最好的一個。較少的分支(取決於當然如何在libc中實現floor())。我會試一試並報告我的結果。 – orj 2011-03-14 22:17:10

+0

無賴。第二個實施選項不通過測試。首先是。 – orj 2011-03-14 22:22:03

+0

糟糕。全腦失敗。再試一次。抱歉! – 2011-03-14 22:50:37

1

lrint()可能會更快。

inline double fwrap(double x, double y) 
{ 
    return x - y * lrint(x/y - 0.5); 
} 

double constrain(double x, double lo, double hi) 
{ 
    return fwrap(x, hi - lo); 
} 
1

lrint()可能會更快。

inline double fwrap(double x, double y) 
{ 
    return x - y * lrint(x/y - 0.5); 
} 

double constrain(double x, double lo, double hi) 
{ 
    return fwrap(x - lo, hi - lo) + lo; 
} 
0

這也適用於:

double constrain(double value, double min, double max) 
{ 
    double Range = max - min; 

    if (value < min) 
     value = max - (max - value) % (Range + 1); // Range+1 for inclusive 

    if (value > max) 
     value = (value - min) % (Range) + min; // Range(+0) for exclusive 

    return value; 
}