먼저 파이썬 인터프리터를 실행하여 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 언어로 각각 테스트해 보았습니다.

 

Python 언어로 0.3 - 0.2 - 0.1 계산하기

 

C# 언어로 0.3 - 0.2 - 0.1 계산하기

 

 

C 언어로 0.3 - 0.2 - 0.1 계산하기

 

Posted by Scripter
,

gmplib 의 현재 최신 릴리즈는 2020년 11월 14일에 출시된 gmplib 6.2.1 이다.

우선 이곳에서 압축 파일을 하나 다운로드한다.

여기서는 gmp-6.2.1.tar.xz 을 다운로드한 것으로 간주하고 설치 과정을 소개한다.

우선 tar 명령으로 다운로드한 파일의 압축을 해제한다.

(아래에서 $ 는 쉘 프롬프트이므로 입력하지 않아먀 한다.)

$ tar Jxvf gmp-6.2.1.tar.gz

위 명령에 의하여 현제 폴더에 gmp-6.2.1 이라는 폴더가 생기면서

압축된 것들이 이 폴더 아래에 해제된다.

이제 cd 명령으로 그 하위 폴더로 이동한다.

$ cd gmp-6.2.1

configure 명령으로 설치하기 전 설정을 한다.

여기서 옵션 --enable-cxx 는 #include <gmpxx.h> 구문으로

c++ 언어를 사용하기 위함이다.

./configure --enable-cxx

이제 make 명령으로 빌드한다.]

$ make

설치 전에 빌드한 것을 체크한다.

make check

빌드된 것을 /usr/local 폴더에 설치한다.

이 풀더에는 관리자 권한으로 쓰기 작업해야 하므로 sudo 명령이 필요하다.

(사용자의 개인 폴더에 설치할 때는 sudo 명령이 없어도 된다.)

$ sudo make install

설치 과정 중에 파생된 잡다한 파일들을 제거한다.


make clean

c++ 용 에제 소스를 작성하고 more 명령으로 확인한다.

more test-gmp.cc
#include <iostream>
#include <gmpxx.h>

using namespace std;

int main (void)
{
  mpz_class a, b, c;

  a = 1234;
  b = "-5678";
  c = a+b;
  cout << "sum is " << c << "\n";
  cout << "absolute value is " << abs(c) << "\n";

  return 0;
}


작성된 위의 소스를 g++ 명령으로 컴파일한다.


g++ -o test-gmp test-gmp.cc -lgmpxx -lgmp

 

컴파일 하여 생성된 파일을 실행한다.


./test-gmp
sum is -4444
absolute value is 4444

 

 

 

Posted by Scripter
,

 

0.3 - 0.2 - 0.1 == 0.0

 

0.3 - 0.2 - 0.1 != 0.0

 

0.3 - 0.2 - 0.1 -eq 0.0

 

0.3 - 0.2 - 0.1 -ne 0.0

 

PowerShell 뿐만 아니라 배정말도 부동소수점수(IEEE754-1987 포맷) 계산에서는 

십진수로 유효수자(sifnificant digits) 개수가 약 15개 밖에 안되므로

모든 소수점수를 근사값으로 계산한다. (mantissa 가 52bit, 부호가 1bit, 지수부가 11bit 로 총 64bit 즉, 8byte)

 

 

 

 



        Byte 7     Byte 6      Byte 5    Byte 4      Byte 3    Byte 2     Byte 1    Byte 0                                                                       Byte 0
       --------   --------   --------   --------   --------   --------   --------   --------
          6            5            4               3           2              1
       32109876   54321098   76543210   98765432   10987654   32109876   54321098   76543210 
       ========   ========   ========   ========   ========   ========   ========   ========
       snnnnnnn   nnnnbbbb   bbbbbbbb   bbbbbbbb   bbbbbbbb   bbbbbbbb   bbbbbbbb   bbbbbbbb
       ========   ========   ========   ========   ========   ========   ========   ========
       S    Exponent           Mantissa
      63[    62 ~ 52 ][         51 ~ 0                                                    ]
      
      
      
                   (Sign) (1.bbbbb....bbbbb)_2 * pow(2, (nnnnnnnnnnn)_2 - 307)
                     +/-     1 bit + 53 bits                22 bits       bias
                            -----------------
                                54 bits
                                   
       -

 

 

Posted by Scripter
,