2010-08-08 27 views
7

Necesito ayuda para resolver un error extraño - cuando uso el operador mod (%) en x86 todo bien, Pero en x64 me sale a veces NaN como residuo (por lo general ocurre con Angle = 0). Logré reproducir ese error fuera de mi código, pero solo con Angle = double.Epsilon (en mi código también ocurre con Angle = 0).Operador Mod (%) en x86 vs x64

class Program 
{ 
    public const double M_PI = 3.14159265358979323846; 
    static void Main(string[] args) 
    { 
     double m_2PI = (2 * M_PI); 
     double m_Angle = double.Epsilon; 
     double mod = (m_Angle % m_2PI); 
     //x86 mod = 4.94065645841247E-324 
     //x64 mod = NaN 
     if (double.IsNaN(mod)) 
      Debug.Write(mod); 
    } 
} 

Saludos, Shay

+0

No estoy tan seguro de que sea un error: los puntos flotantes x86 y x64 pueden arrojar resultados diferentes. Tal vez solo necesites trabajar en eso. –

+1

Consejo pequeño: puede usar 'Math.PI' en lugar de especificarlo como su propia constante –

Respuesta

1

Esto no es un bicho raro, en lugar de un error bastante esperada. Si se encuentra en el rango externo de un tipo de datos numéricos y juega con operaciones, me sorprendería que esto no ocurra.

Una solución podría estar encapsulando la función de modificación.

static double myMod(double v, double m){ 
    if(v < m) return v; 
    return v % m; 
} 

¿Puedo preguntar, por qué te preocupas por un caso límite?

+7

Claramente, los casos límite son muy importantes. Representan una gran cantidad de errores en el software de producción. –

+0

La función dada es incorrecta si 'v' o' m' pueden ser negativos. – phoog

1

En C# el operador de módulo puede tomar más de los valores int de C habituales. Pero sí, creo que hay diferencias entre los ISA cuando estás haciendo cantidades épsilon.

En su caso, el épsilon en un número suficientemente pequeño para causar el NAN.

Vea si puede reproducirlo con flotador y otros tipos. Si puede usarlos, el problema está "resuelto".

Como solución, puede hacer las operaciones usted mismo con épsilon y simplemente devolver 0 en ese caso.

0

Descargo de responsabilidad: No soy un programador .Net.

Pero esto suena como un error. La operación está bien definida para las entradas que suministró, y debe devolver m_Angle. Supongo que la implementación intenta incondicionalmente la división m_Angle/m_2PI, que desciende por sus entradas. Evidentemente, el manejo de esta condición difiere entre las plataformas de 32 bits y 64 bits. Esto podría haberse hecho correctamente usando algo similar a la respuesta de Marcus Johansson, a costa de una ligera penalización de tiempo de ejecución de para la verificación de rango adicional.

Cuestiones relacionadas