2010-01-13 4 views
8

나는 Java의 알고리즘/계산법과 그에 대한 단위 테스트를 가지고 있습니다. 단위 테스트는 약간의 정밀도/델타를 가진 결과를 기대합니다. 이제 저는 algo를 .NET으로 포팅하고 동일한 단위 테스트를 사용하고자합니다. 더블 데이터 형식으로 작업합니다..NET의 엄격한 부동 소수점 수학을위한 라이브러리

문제는 Java가 Math 클래스의 일부 연산에 strictfp (64 비트)를 사용한다는 것입니다. .NET은 항상 FPU/CPU를 사용합니다 (80 비트). .NET은보다 정확하고 빠릅니다. Java는 더 예측 가능합니다.

내 알 고리가 순환적이고 이전 라운드의 결과를 재사용하기 때문에 오류/차이/세부 정밀도가 너무 커집니다. 나는 속도에 의존하지 않는다 (단위 테스트 용). 그리고 프로덕션 환경에서 .NET 정밀도를 사용하게되어 기쁩니다. 그러나 구현을 검증하고 싶습니다.

내가 라이브러리 또는 .NET 엄격한 FP를 사용하는 방법을 찾고 있어요 JDK


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

에서 이것을 고려하십시오.

선매 논평 : IEEE 754 형식과 부동 소수점 숫자가 정확한 십진수 또는 소수가 아니라는 사실을 알고 있습니다. Decimal 없음, BigInt 또는 BigNumber 없음 제발 이런 식으로 대답 하지마. 고마워.

+3

단위 테스트와 생산간에 다른 부동 소수점 연산을 사용하는 경우 단위 테스트가 테스트하는 내용을 이해하지 못합니다. .NET 구현에만 나타나는 오류를 잡을 위험이 있습니까? –

+0

algo/math는 더 큰 통합 테스트의 일부입니다. 그래서 정확히 똑같이 작동하려면이 구성 요소가 필요합니다. 테스트를 위해서 Java와 동일한 (엄격한) 반올림이 있어야하는데 실제로는 덜 정확합니다. –

+0

더 악화 될 수 있습니다. 이 토론에서는 CLR이 80 비트 x87 부동 소수점 또는 64 비트 SSE2를 사용하도록 코드를 컴파일하기로 결정했다고 제안합니다. https://connect.microsoft.com/VisualStudio/feedback/details/276107/provide-access 부동 소수점 컨텍스트 –

답변

2

불행히도 C#에서 FP 엄격 성을 적용 할 방법이 없으며 .Net CLR은 최대한 낮은 정밀도로 계산을 수행 할 능력이 부족합니다.

성능 향상이 있다고 생각합니다. 정밀도가 떨어질 수 있는지 확인하지 않습니다. 또한 필요도 없습니다. .NET은 가상 머신에서 실행되지 않으므로 다른 부동 소수점 프로세서에 대해 걱정하지 않아도됩니다.

그러나 strictfp은 선택 사항이 아닙니까? strictfp 수정 자없이 Java 코드를 실행할 수 있습니까? 그럼 .Net과 동일한 부동 소수점 메커니즘을 선택해야합니다.

strictfp을 강제로 사용하는 대신 Java 코드와 동일한 값이 나오는지 확인하십시오. Java가 strictfp을 사용하지 않도록하고 그 값을 확인하십시오. 그런 다음 .Net 코드와 동일하게 나타납니다.

+1

좋은 생각입니다. strictfp를 사용하지 않으려면 Java Math 클래스를 다시 구현해야하며 런타임의 원시 코드에 strinc로 구현되지 않았 으면합니다. 그러나 그것은 문제를 완전히 해결하지 못합니다 (이제 저는 단 정치 못하게되었습니다). 코드에서 하드 코딩 된 일부 상수 결과가 있기 때문에 나중에 differen 하드웨어에서 단위 테스트를 실행하면 실패합니다. 음, 더 좋은 대답은 없습니다. 어쨌든 당신은 경주에서 승리했습니다 :-) –

2

.NET에서 부동 소수점 산술에 대한 멀티 플레이어 시뮬레이션을 기반으로 할 수 있는지 알고 싶었 기 때문에 올해 초이 문제를 광범위하게 조사했습니다. 내 결과 중 일부는 유용 할 수 있습니다.

It is possible to emulate "strict" mode by inserting redundant casts everywhere 그러나이 방법은 취성있는 C# 전용의 지루한 솔루션입니다.

32 비트 JIT는 x87 명령어를 방출하지만 64 비트 JIT는 SSE 명령어를 방출합니다. 이는 Microsoft와 Mono의 구현 모두에 해당됩니다. x87과 달리 SSE floating arithmetic is reproducible.

나는 System.Math가 단순히 동일한 C 런타임 함수를 호출한다고 믿지만, 이것을 확인하기 위해 어셈블리를 사용할 수는 없다. (만약 누군가가 이것을 어떻게하는지 안다면, 확인해 보라!). 가능한 경우 C 런타임은 초급 함수의 SSE 버전을 사용합니다. 단 몇 가지 경우를 제외하고는 특히 sqrt를 사용합니다 (그러나 인트 멘 트린을 통해 래퍼를 작성하는 것은 간단합니다). SSE의 본성에 의해 재현 가능해야합니다. It is programatically possible to determine whether the C runtime is using its SSE implementation rather than x87.

SSE (fmod, sinh, cosh, tanh)에서 사용할 수없는 나머지 초월 함수의 경우 결과가 x87에서 더 이상 연산을 수행하지 않으면 재현성 문제가 발생하지 않을 수 있습니다.

간단히 말해서 64 비트 CLR을 고수하면 산술 문제가 해결됩니다. 초월 함수의 경우, 대부분은 SSE에서 이미 구현되어 있으며, x87 산술 연산을 수행하지 않을 경우 필요하다는 것을 확신하지 못합니다.