C: Как обернуть поплавок в интервал [-pi, pi) - PullRequest
31 голосов
/ 08 января 2011

Я ищу хороший C-код, который будет эффективно выполнять:

while (deltaPhase >= M_PI) deltaPhase -= M_TWOPI;
while (deltaPhase < -M_PI) deltaPhase += M_TWOPI;

Какие у меня варианты?

Ответы [ 15 ]

0 голосов
/ 02 октября 2015

Если вы ссылаетесь на libm glibc (включая реализацию newlib), вы можете получить доступ Частные функции __ieee754_rem_pio2f () и __ieee754_rem_pio2 ():

extern __int32_t __ieee754_rem_pio2f (float,float*);

float wrapToPI(float xf){
const float p[4]={0,M_PI_2,M_PI,-M_PI_2};

    float yf[2];
    int q;
    int qmod4;

    q=__ieee754_rem_pio2f(xf,yf);

/* xf = q * M_PI_2 + yf[0] + yf[1]                 /
 * yf[1] << y[0], not sure if it could be ignored */

    qmod4= q % 4;

    if (qmod4==2) 
      /* (yf[0] > 0) defines interval (-pi,pi]*/
      return ( (yf[0] > 0) ?  -p[2] : p[2] ) + yf[0] + yf[1];
    else
      return p[qmod4] + yf[0] + yf[1];
}

Edit: только что понял, что вам нужно ссылку на libm.a, я не смог найти символы, объявленные в libm.so

0 голосов
/ 25 июня 2013

В C99:

float unwindRadians( float radians )
{
   const bool radiansNeedUnwinding = radians < -M_PI || M_PI <= radians;

   if ( radiansNeedUnwinding )
   {
      if ( signbit( radians ) )
      {
         radians = -fmodf( -radians + M_PI, 2.f * M_PI ) + M_PI;
      }
      else
      {
         radians = fmodf( radians + M_PI, 2.f * M_PI ) - M_PI;
      }
   }

   return radians;
}
0 голосов
/ 16 апреля 2013

Способ, предложенный вами, предложен лучше всего.Это самый быстрый для небольших отклонений.Если углы в вашей программе постоянно отклоняются в надлежащий диапазон, то вы должны редко сталкиваться с большими значениями вне диапазона.Поэтому платить за сложный модульный арифметический код каждый раунд кажется расточительным.Сравнения дешевы по сравнению с модульной арифметикой (http://embeddedgurus.com/stack-overflow/2011/02/efficient-c-tip-13-use-the-modulus-operator-with-caution/).

0 голосов
/ 13 апреля 2012

Я использовал (в Python):

def WrapAngle(Wrapped, UnWrapped ):
    TWOPI = math.pi * 2
    TWOPIINV = 1.0 / TWOPI
    return  UnWrapped + round((Wrapped - UnWrapped) * TWOPIINV) * TWOPI

Эквивалент c-кода:

#define TWOPI 6.28318531

double WrapAngle(const double dWrapped, const double dUnWrapped )
{   
    const double TWOPIINV = 1.0/ TWOPI;
    return  dUnWrapped + round((dWrapped - dUnWrapped) * TWOPIINV) * TWOPI;
}

обратите внимание, что это переносит его в обернутый домен +/- 2pi, поэтому для домена +/- pi вам нужно обработать это позже, как:

if( angle > pi):
    angle -= 2*math.pi
0 голосов
/ 08 января 2011

deltaPhase -= floor(deltaPhase/M_TWOPI)*M_TWOPI;

...