2011-03-14 39 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; 
}