먼저 파이썬 인터프리터를 실행하여 0.3 - 0.2 - 0.1 의 계산 결과를 알아 보았습니다.
>>> 0.3 - 0.2 - 0.1
-2.7755575615628914e-17
계산 결과가 왜 0이 아닌 엉뚱한 값 -2.7755575615628914e-17 이 될까요?
IEEE754 에 대해서는 관련되는 두 문서
[1] Double-precision floating-point format
[2] Floating Point Arithmetic: Issues and Limitations
를 참고하기 바랍니다.
NET Framework 4.6.x 이상에서 사용가능한 NET용 분수 계산 라이브러리를 소개합니다.
(소스 수정 없이 NET Core 5.0 이상에서도 사용 가능합니다.)
(Mac OS 에서도 FractionLib 를 빌드하여 쓸 수 있습니다만, UnitTest 프로젝트는 새로 작성해야 합니다.)
FractionLib project 에서 내려받은 프로젝트 파일을
Vusual Studio 2019 이상에서 빌드하여 생성된 FractionLib.dll을,
다른 프로젝트에서 라이브러리로 참조 사용하면 IEEE754 의 배정밀도 부동소숫점수를
분수로 받아들여 보다 정확한 수치 계산을 할 수 있습니다.
내부적으로 C#의 표준 큰 정수 BigInteger를 이용하므로 System.Numerics,dll을
함께 참조 추가하면 더 좋습니다.
FractionLib,dll을 사용할 수 있는 언어로는 C# 언어 외에 F#, Visual Basic, IronPython, C++/CLI
언어들도 가능합니다.
사용 예제는 위 프로젝트의 Examples 폴더에 있습니다.
부동소수점수의 뺄셈 계산
0.3 - 0.2 - 0.1
의 계산 결과는 당연히 0이 되어야 함에도 불구하고
IEEE 754에서 정한 부동소수점수의 한계(mantissa, 유효숫지 부분의 한계)
때문에 0.3 - 0.2 - 0.1 의 계산 결과가 0이 아닌 적당한 근사값로 계산되며,
그 역수는 -1.0E20 보다 큰 음수로 계산됩니다.
그러나 FractionLib.dll 을 사용하여
using knumerics;
......................
......................
MyFraction a3 = new MyFraction(0.3);
MyFraction a2 = new MyFraction(0.2);
MyFraction a1 = new MyFraction(0.1);
MyFraction zero = new MyFraction(0, 1);
MyFraction result = a3 - a2 - a1;
Console.WriteLine("result == zero ? {0}", result == zero);
로 작상하면 0.3 - 0.2 - 0.1의 계산 결과가 정확히 0이 됩니다.
참고로, 온라인 상에서 Python 언어, C# 언어, C 언어로 각각 테스트해 보았습니다.
'프로그래밍 > C#' 카테고리의 다른 글
C# 언어에서 큰 부동소수점수(native double) 의 정확도 (0) | 2023.03.19 |
---|---|
0.3 - 0.1 == 0.2 ? (0) | 2020.12.14 |
Visual Studio 2019 에서 유닛 테스트 작성하는 예 (0) | 2020.04.21 |
C# 의 세제곱근 구하는 함수 Cbrt() (0) | 2020.03.25 |
원시 피타고라스 삼조를 생성하는 C# 소스 (0) | 2020.03.01 |