2012-02-29 31 views
16

Estoy tratando de implementar la operación de reducción de rango para trigonometría. Pero, en cambio, creo que sería mejor simplemente realizar una operación de módulo pi/2 en los datos entrantes. Me preguntaba qué algoritmos existen y son eficientes para esta operación para el punto flotante IEEE 754 de 32 bits.Operación de módulo de coma flotante

Tengo que implementar esto en el montaje, por lo que fmod, división, multiplicación, etc. no están disponibles para mí con solo una instrucción. Mi procesador usa palabras de 16 bits y he implementado suma, resta, multiplicación, división, raíz cuadrada, coseno y seno en coma flotante de 32 bits. Solo necesito la reducción de rango (módulo) para ingresar valores al coseno y al seno.

+4

En realidad, hay muchos algoritmos inteligentes, por ejemplo google para "reducción de rango payne hanek", pero creo que eso no es lo que quieres – hirschhornsalz

+1

El documento de Ng al que has vinculado en una pregunta previa tuya en realidad explica el Payne-Hanek algoritmo, que AFAIK sigue siendo el estado de la técnica para una reducción de rango precisa. Solo tienes que adaptarlo a una sola precisión. – janneb

+0

@Todo el mundo, elimine/edite su respuesta para que se aplique a mi pregunta real. Estoy buscando el algoritmo dentro de un módulo de coma flotante. Necesito implementar lo que hace fmod y minimizar el número de divisiones que realizo. – Veridian

Respuesta

14

pienso de fmod() biblioteca estándar será la mejor opción en la mayoría de los casos. Aquí hay un link para una discusión de varios algoritmos simples.

En mi máquina, fmod() usos en línea optimizado código de montaje (/usr/include/bits/mathinline.h):

#if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) 
__inline_mathcodeNP2 (fmod, __x, __y, \ 
    register long double __value;       \ 
    __asm __volatile__         \ 
    ("1: fprem\n\t"       \ 
    "fnstsw %%ax\n\t"        \ 
    "sahf\n\t"         \ 
    "jp 1b"        \ 
    : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");   \ 
    return __value) 
#endif 

lo que en realidad utiliza una instrucción de CPU dedicada (fprem) para el cálculo.

+0

Oh, en realidad estoy tratando de implementar lo que hace fmod. Ese es el problema, estoy buscando el algoritmo de módulo para coma flotante. – Veridian

+0

La forma más directa es probablemente (código tomado del enlace en mi publicación, pero es una especie de definición de módulo para coma flotante y por lo tanto la forma obvia de hacerlo): plantilla T fmod (T x, T y) { T a = (T) (larga longitud) (x/y); return x - a * y; } –

+0

Estoy un poco preocupado por redondear ese producto * y, pero no estoy seguro de cómo mitigarlo. – zmccord

12

Quizás me esté faltando el punto aquí, pero ¿tiene algo en contra de simplemente usar fmod?

double theta = 10.4; 
const double HALF_PI = 2 * atan(1); 
double result = fmod(theta, HALF_PI); 
+0

Vale la pena subir un voto en ese momento. –

+0

Oh, en realidad estoy tratando de implementar lo que hace fmod. Ese es el problema, estoy buscando el algoritmo de módulo para coma flotante. – Veridian

+2

'fmod' está bien siempre y cuando no le importe la precisión con argumentos grandes. – hirschhornsalz

7

El algoritmo desea, para limitar un punto value flotando entre 0 y algunos módulo n:

Double fmod(Double value, Double modulus) 
{ 
    return value - Trunc(value/modulus)*modulus; 
} 

por ejemplo pi mod e (3.14159265358979 mod 2,718281828459045)

3.14159265358979/2.718281828459045 
    = 1.1557273497909217179 

Trunc(1.1557273497909217179) 
    = 1 

1.1557273497909217179 - 1 
    = 0.1557273497909217179 

0.1557273497909217179 * e 
    = 0.1557273497909217179 * 2.718281828459045 
    = 0.42331082513074800 

pi mod e = 0.42331082513074800

+2

Esto fue particularmente útil para mí porque, aunque la pregunta inicial se formuló en el contexto de la programación C/C++, llegué a esta pregunta en particular que necesitaba una fórmula general para hacerlo en un sistema de números de punto fijo en el que estoy trabajando. Me alegro de que hayas publicado esto, porque fmod() no era una solución a mis necesidades, aunque podría haber sido para el OP. Hay bastantes personas que necesitan esta fórmula en particular en otros contextos. –

+0

Esto puede ser [muy inexacto para '' valores 'grandes'] (https://stackoverflow.com/questions/9505513/floating-point-modulo-operation/37977740#comment12038890_9505761). Hay algoritmos más sofisticados. Pero esto generalmente será bastante rápido, por lo que es una buena opción si está numéricamente bien para su caso de uso. –

Cuestiones relacionadas