Aquí podría ser tu PUBLICIDAD


¿Cómo debo abordar ARCTAN (y evitar decargar por cero) sin la conveniencia de que ARCTAN2 (n, m) esté disponible?

votos
4

Intento determinar el ángulo desde un punto (n,m)a (0,0). Sin arctan2estar disponible, me estoy encontrando con el problema que mpuede ser 0, lo que lleva a una posible división por cero.

¿Cuál sería una solución elegante y correcta para abordar este problema?

Publicado el 12/03/2009 a las 16:56
fuente por usuario Kriem
En otros idiomas...        العربية       

5 respuestas

votos
2

no use los cuadrantes convencionales, use los puntos de bifurcación definidos por las líneas y = +/- x, y use los primeros dos pasos de un algoritmo tipo CORDIC (por ejemplo, gire las coordenadas en un ángulo conocido y lleve un registro de cuánto rotado):

function atan2_substitute(x,y)
{
   double angle = 0;
   if (x < y)
   { angle = M_PI; x = -x; y = -y; }
   // this guarantees that the angle is between -135 and +45 degrees

   if (x < -y)
   {
     angle -= M_PI/2; tmp = x; x = -y; y = tmp;
   }
   // this guarantees that the angle is between -45 and +45

   angle += atan(y/x);

   if (angle > M_PI)
      angle -= 2*M_PI;
   // fails at 0,0; otherwise is accurate over the entire plane
}

la razón para hacerlo de esta manera es que atan () puede ser más preciso para proporciones y / x entre -1 y +1, que para relaciones mayores que 1. (aunque un buen algoritmo atan () reconocería esto y tomar el recíproco)

Respondida el 12/03/2009 a las 05:43
fuente por usuario Jason S


Aquí podría ser tu PUBLICIDAD


votos
1

Implementar el estándar arctan(n, m)usando series de Taylor y hacer lo siguiente antes de calcular arctg:

if (m == 0) {
    if (n < 0) return Pi;
    return 0;
}

Otro par de trucos:

1) si |m| < |n|, de intercambio m, ny luego calcular arctg. Finalmente restar el resultado dePi/2

2) si |m|está cerca de |n|, calcular arctan del medio ángulo usando la fórmula media ángulo arctan(x) = 2*arctan(x/(1+sqrt(1+x*x))), de lo contrario, para tales valores, arctan converge muy lentamente

Respondida el 25/01/2010 a las 10:46
fuente por usuario Jus12

votos
1

Si atan2 no está disponible, debe verificar la condición dividir por cero y todos los demás casos especiales en su código. Tan fácil como eso. La entrada de wikipedia en atan2 tiene todas las condiciones que necesita.

Si su hardware de destino admite excepciones de división por cero para operaciones de coma flotante, tiene otra opción:

Instale un controlador de bajo nivel que verifique la causa de la excepción y, si resulta ser una división atan, solucione el problema. Esto hará que tu atan2 sea más rápido si las excepciones son raras, pero requiere retoques de bajo nivel y no es portátil.

Respondida el 12/03/2009 a las 05:13
fuente por usuario Nils Pipenbrinck

votos
0

Creo que esta es una implementación correcta de atan2 usando atan (aunque no maneja infinitos):

float my_atan2(float y, float x)
{
    if(x == 0) // might also want to use fabs(x) < 1e-6 or something like that
    {
        if(y > 0)
            return M_PI_2;
        else
            return -M_PI_2;
    }
    else if(x > 0)
    {
        return atan(y/x);
    }
    else 
    {
        // x < 0                                                                                
        if(y > 0)
            return M_PI + atan(y/x);
        else
            return -M_PI + atan(y/x);
    }
}

Arnés de prueba:

int main()
{
    for(int i = -360; i <= 360; i++)
    {
        float x = cos(i / 180.0 * M_PI);
        float y = sin(i / 180.0 * M_PI);


        float good = atan2(y, x);
        float mine = my_atan2(y, x);


        if(fabs(good - mine) > 1e-6)
        {
            printf("%d %f %f %f %f\n", i, x, y, good, mine);
        }
    }
}
Respondida el 12/03/2009 a las 05:24
fuente por usuario Jesse Rusak

votos
0

Defina su versión de arctan2. Un ejemplo en C como macro:

#define atan2(n,m)   (m)==0 ? M_PI_2 : atan((n)/(m))

Por supuesto, puede elaborar para encontrar el cuadrante según los signos de ny m.

Respondida el 12/03/2009 a las 05:09
fuente por usuario mouviciel