2010-01-13 11 views
8

Tengo algoritmo/cálculo en Java y prueba de unidad para él. La prueba unitaria espera resultados con cierta precisión/delta. Ahora porté el algoritmo en .NET y me gustaría usar la misma prueba unitaria. Yo trabajo con doble tipo de datos.Biblioteca de punto flotante estricto Matemáticas en .NET

El problema es que Java usa strictfp (64bits) para algunas operaciones en la clase Math. Donde como .NET utiliza FPU/CPU siempre (80 bits). .NET es más preciso y más rápido. Java es más predecible.

Como mi algo es cíclico y reutiliza los resultados de la ronda anterior, el error/diferencia/más precisión se acumula demasiado grande. No confío en la velocidad (para la prueba unitaria). Y me complace utilizar la precisión .NET en producción, pero me gustaría validar la implementación.

Considere esto desde JDK


public final class Math { 
    public static double atan2(double y, double x) { 
    return StrictMath.atan2(y, x); // default impl. delegates to StrictMath 
    } 
} 

Busco biblioteca o técnica a utilizar estricta FP en .NET.

Comentario preventivo: Entiendo el formato IEEE 754 y el hecho de que el número de coma flotante no es el número o fracción decimal exacta. Sin decimales, sin BigInt o BigNumber. Por favor, no responda de esta manera, gracias.

+3

No entiendo lo que su unidad de prueba está probando si utiliza diferentes implementaciones de coma flotante de matemáticas entre la Unidad de Pruebas y Producción. ¿No corre el riesgo de no detectar un error que solo se manifiesta con la implementación de .NET? –

+0

El algoritmo/matemática es parte de una prueba de integración más grande. Entonces necesito que este componente se comporte exactamente igual. Solo para la prueba debería tener el mismo redondeo (estricto) que Java, que en realidad es menos preciso. –

+0

Puede ser aún peor. Esta discusión sugiere que CLR puede decidir compilar el código para usar 80-bit x87 coma flotante o SSE2 de 64 bits: https://connect.microsoft.com/VisualStudio/feedback/details/276107/provide-access -to-the-floating-point-context –

Respuesta

2

Desafortunadamente no hay forma de imponer el rigor de FP en C#, el .Net CLR simplemente carece de la capacidad de hacer cálculos con menos precisión que el máximo posible.

Creo que hay una ganancia de rendimiento para esto; no comprueba que pueda querer menos precisión. Tampoco es necesario: .Net no se ejecuta en una máquina virtual, por lo que no se preocupa por los diferentes procesadores de punto flotante.

Sin embargo, ¿no es strictfp opcional? ¿Podría ejecutar su código Java sin el modificador strictfp? Entonces debería recoger el mismo mecanismo de coma flotante como .Net

Así que en lugar de forzar a .Net utilizar strictfp y la comprobación de que salga con los mismos valores que el código Java que podría obligar a Java para no utilizar strictfp y comprobar que luego sale igual que el código .Net.

+1

Esa es una buena idea. Probablemente necesite volver a aplicar la clase de Java java para no usar strictfp y espero que no se implemente como strinc en el código nativo del tiempo de ejecución. Pero no resuelve el problema por completo (ahora solo estoy criticando). Porque tengo algunos resultados esperados constantes codificados en código, así que si ejecuto la prueba unitaria en hardware diferente más tarde, fallará ... Bueno, no hay mejor respuesta de todos modos, ganaste la carrera :-) –

2

He investigado extensamente este problema a principios de este año, ya que quería saber si era posible basar una simulación multijugador en aritmética de coma flotante en .NET. Algunos de mis hallazgos pueden serle útiles:

It is possible to emulate "strict" mode by inserting redundant casts everywhere, pero esta parece ser una solución frágil, específica de C# y tediosa.

El JIT de 32 bits emite instrucciones x87, pero el JIT de 64 bits emite instrucciones SSE. Esto es cierto tanto en la implementación de Microsoft como en la de Mono. A diferencia de x87, SSE floating arithmetic is reproducible.

Creo que System.Math simplemente llama a las funciones de tiempo de ejecución C equivalentes, aunque no he podido entrar en el conjunto para verificar esto (si alguien sabe cómo hacerlo, compruebe). El tiempo de ejecución de C utiliza versiones SSE de funciones trascendentales cuando es posible, excepto en algunos casos, notablemente sqrt (pero escribir un contenedor a través de instrinsics para eso es trivial). Por la naturaleza misma de SSE, estos deben ser reproducibles. It is programatically possible to determine whether the C runtime is using its SSE implementation rather than x87.

Para las funciones trascendentales restantes no disponibles en SSE (fmod, sinh, cosh, tanh), es posible que no causen problemas de reproducibilidad si no se realiza ninguna operación adicional en x87 con su resultado.

En resumen, seguir con CLR de 64 bits debería resolver el problema de la aritmética; para funciones trascendentales, la mayoría ya están implementadas en SSE y ni siquiera estoy seguro de que eso sea necesario si no realiza ninguna aritmética x87 con los resultados.

Cuestiones relacionadas