大多数简洁的浮点约束函数的实现具有环绕溢出 [英] Most succinct implementation of a floating point constraint function with wrap-around overflow

查看:175
本文介绍了大多数简洁的浮点约束函数的实现具有环绕溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

其中的Constrain()边界 value 范围 [min,float)。也就是说,范围包括min,但不包括 max 大于 max 或小于 min 环绕在一个圆圈中。即,以类似的方式整数溢出/下溢。

该函数应通过以下测试:

<$ p (0.0,0.0,10.0)== 0.0
约束(10.0,0.0,10.0)== 0.0
约束(5.0,0.0,10.0)== 5.0
约束(15.0,0.0,10.0)== 5.0
约束(-1.0,0.0,10.0)== 9.0
约束(-15.0,0.0,10.0)== 5.0

约束(0.0,-5.0,5.0)== 0.0
约束(5.0,-5.0,5.0)== -5.0
约束(0.0,-5.0,5.0)== 0.0
约束(10.0,-5.0,5.0)== 0.0
约束(-6.0,-5.0,5.0)== 4.0
约束(-10.0,-5.0,5.0)== 0.0
约束(24.0,-5.0,5.0)== 4.0

约束(0.0,-5.0,0.0)== -5.0
约束(5.0,-5.0,0.0) == -5.0
约束(10.0,-5.0,0.0)== -5.0
约束(-3.0,-5.0,0.0)== -3.0
约束(-6.0,-5.0 ,0.0)== -1.0
约束(-10.0,-5.0,0.0)== -5.0

请注意, min 参数可以假设始终在数值上小于 max



可能有一个非常简单的公式来解决这个问题,但是我很惊讶,不知道这个广义的解决方案。
几乎寻找 fmod fmod(x,y)通过 y x $ c>,都是 double s。结果的符号与 x 相同(相应地,相应的整数部分函数是向零回绕的函数),这就是为什么它只是几乎你想要什么。所以,如果 x> = lo ,那么 lo + fmod(x-lo,hi-lo)是正确的事,但如果 x 那么 hi + fmod(x-lo,hi-lo)除了当 x 和结果可以是 lo hi 你得到 hi 而不是 lo



所以。你可以分成三种方式:

$ p $ double Constrain(x,lo,hi){
double t = fmod(x -lo,高低);
返回t <0? t + hi:t + lo;

$ / code>

或者您可以使用 floor 改为:
$ b $ pre $ double Constrain(x, lo,hi){
double t =(x-lo)/(hi-lo);
return lo +(hi-lo)*(t-floor(t));



$ b $ p
$ b

如果你关心的是可理解性,如果你关心的是性能,试试它们。


I'm looking for the most succinct and general implementation of the following function:

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

Where Constrain() bounds value in the range [min, float). Ie, the range includes min but excludes max and values greater than max or less than min wrap around in a circle. Ie, in a similar way to integers over/underflow.

The function should pass the following tests:

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

Note that the min param can be assumed to be always numerically less than max.

There is probably a very simple formula to solve this question but and I'm being spectacularly dumb not knowing the generalised solution to it.

解决方案

You're almost looking for the fmod function. fmod(x,y) returns the remainder on dividing x by y, both being doubles. The sign of the result is the same as that of x (equivalently, the corresponding integer-part function is the one that rounds towards zero), and that's why it's only almost what you want. So, if x>=lo then lo+fmod(x-lo,hi-lo) is the Right Thing, but if x<lo then hi+fmod(x-lo,hi-lo) is oh-so-nearly the Right Thing except that when x<lo and the result could be either lo or hi you get hi instead of lo.

So. You can split three ways:

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

or you can use floor instead [EDITED because the first version of this wasn't what I meant at all]:

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

Take your pick if what you care about is comprehensibility; try them both if what you care about is performance.

这篇关于大多数简洁的浮点约束函数的实现具有环绕溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆