정수의 곱셈을 빨리하기 위한 방법 중의 하나로

기수법으로 표현된 정수를 여러 조각으로 분할하여

덧셈이나 뺄셈 회수는 몇회 증가하는 대신, 곱셈 횟수를 몇회 감소하는

방법입니다. 곱셈이 덧셈이나 뺄셈 보다는 시간이 많이 걸린다는

전제 하에 카라츄바 곱셈(Karatsuba multiplication)을 적용하면

시간복잡도 O(N**2) 의 계산 과정을 을 약 시간복잡도 O(N*&1.5)의 계산 과정으로

줄일 수 있습니다.  (여기서 N은 기수법으로 표현된 정수의 분할 개수입니다.)

예를 들어  두 자리 십진법 수 23과 45의 곱셈 23*45을 생각해 봅니다.

(이 경우 N = 2 입니다.)

 

                  2  3
          x )     4  5
            -----------
                  1  5
               1  0
               1  2
               8
            -----------
            1  0  3  5

 

위의 곱셈표에서 보듯이,

   곱셈은 3*5 = 15, 2*5 = 10, 3*4 = 12, 2*4 = 8 로 모두 4회입니다.

   덧셈은 15 + 10 + 12 + 8 로 모두 3회입니다.

그러므로.   곱셈 회수 + 덧셈 회수 = 4(회) + 3(회) = 7(회) 입니다.

 

덧셈이나 뺄셈을 한 후에 곱셈을 할 때는 분배법칙(혹은 배분법칙)

    (a + b)*(c + d) = a*c + b*d + a*d + b*c = (a*c + b*d) + (a*d + b*c)

이 성립하므로 a 에는 2를, b 에는 3을, c에는 4를, d에는 5를 각각 대입하면 

    (2 + 3)*(4 + 5) = 2*4 + 3*5 + 2*5 + 3*4 = (2*4 + 3*5) + (2*5 + 3*4)

 

앞에서 했던 계산 중에 2*5 = 10, 3*4 = 12 은 곱셈이 2회인데,

이 계산을 (2 + 3)*(4 + 5) = (2*4 + 3*5) + (2*5 + 3*4)

즉, 2*5 + 3*4  = (2 + 3)*(4 + 5) - (2*4 + 3*5)  임을 이용하면 곱셈을 1회 줄일 수 있습니다. (덧셈과 뺄셈 회수는 조금 불어닙니다.)

왜냐 하면 2*4 = 8 (10의 자리수 곱셈)과 3*5 = 15 (1의 자리수 곱셈)은 미리 했으므로

(2 + 3)*(4 + 5) 만 계산하고 여기에 미리 계산된 (2*5 + 3*4) 을 뺄셈하면 2*5 + 3*4 을

구 할 수 있습니다.

(2 + 3)*(4 + 5) -  (2*4 + 3*5) = 5*9 - (8 + 15) = 45 - 23 = 22

이 계산에는 덧셈 1회, 뺄셈 1회, 곱셈 1회입니다.

 

                  2  3
          x )     4  5
            -----------
               8  1  5
               2  2          = (2 + 3)*(4 + 5) - (8 + 15) = 45 - 23 = 22
            -----------
            1  0  3  5

 

위의 곱셈표에서 보듯이,

   곱셈은 2*4 = 8, 3*5 = 15, (2 + 3)*(4 + 5) = 45 로 모두 3회입니다.

   덧셈은 2 + 3 = 5, 4 + 5 = 9, 8 + 15 = 23 으로 모두 3회입니다.

   뺄셈은 45 - (8 + 15) 로 1회,

  그리고  815 + 220 에 덧셈 1회 입니다.

  그러므로 덧셈과 뺄셈은 총 5회, 곱셈은 3회가 됩니다.

그러므로.   곱셈 회수 + 덧셈과 뺄셈 회수 = 3(회) + 5(회) = 8(회) 입니다.

 

위의 예에서는 두 자리 십진법 수의 곱셈을 보여주었는데,

이 카라츄바 곱셈 방법은 N자리 r진법  수의 곱셈에도 적용할 수 있습니다.

 예를 들어, 4자리 16진법수 곱셈  0xCAFE * 0xABBA 에도 적용할 수 있습니다.

 

                  C  A  F  E
          x )     A  B  B  A
            ----------------

 

Posted by Scripter
,

Small BASIC은 Microsoft에서 제작 배포하는 BASIC 언어 인터프리터로서

편집기가 내장되어 있으며, 그래픽 기능도 있으며,  Dot NET 4.5 환경에서 동작합니다.

Small BASIC 홈페이지에서 다운로드하여 설치할 수 있으며, 풍부한 튜토리얼도 있습니다.

 

Small BASIC을 설치하고, 처음 실행한 화면입니다.

 

다음의 딱 한줄 을 편집기에 쓰고

TextWindow.WriteLine("Hello World!")

파일 저장하고(파일 확장자가 sb로 저장됨),  실행 버튼 누르면 

Hello World! 가 출력된 컨솔창이 뜹니다.

아래의 몇 줄을 입력하고

Turtle.Show()
For i = 1 To 45
  Turtle.Turn(8)
  Turtle.Move(10)
EndFor

저장 버튼 누르고, 실행 버튼 누르면 아래 처럼 그래픽이 그려집니다.

 

 

Posted by Scripter
,

2차방정식  $$ ax^2 + bx + c = 0 $$

(단, $a != 0$)의 근을 구하는 공식

$$ x = \dfrac{-b \pm \sqrt{b^2 - 4ac}}{2a} $$

 

황금율(golden ratio)을 구하는 2차방정식  $$ x^2 - x - 1  = 0 $$

의 두 근은 

$$ x = \dfrac{1 \pm \sqrt{5}}{2} $$

이고 이 중에 큰 근 $$ x = \dfrac{1 + \sqrt{5}}{2} = 1.618033988749895... $$

이 황금율이다.

 

 

Posted by Scripter
,

피보나치 수열이 0 이상의 정수 n에 대하여

         선형점화공식(linear recurency):  f(n) = f(n - 1) + f(n - 2) 과

         과 초기조건(initial condition):  f(0) = 0,  f(1) = 1

로 정의된 수열인데 이를 음의 정수 n에 대하여도 위의 점화공식을

             f(n) = f(n + 2) - f(n + 1)     (∀ n = -1, -2, -3, -4, -5, ...)

로 고쳐 축차 적용하여 얻어지는 수열

   f(-1), f(-2), f(-3), f(-4), f(-5), ....

네가보나치 수열(negabonacci sequence)이라고 한다.

   즉,

             f(-1) = f(1) - f(0) = 1 - 0 = 1

             f(-2) = f(0) - f(-1) = 0 - 1 = -1

             f(-3) = f(-1) - f(-2) = 1 - (-1) = 2

             f(-4) = f(-2) - f(-3) = -1 - 2 = -3

             f(-5) = f(-3) - f(-4) = 2 - (-3) = 5

             f(-6) = f(-4) - f(-5) = -3 - 5 = -8

             ..............................................

 

 

 

 

 

   

'알고리즘 > 피보나치' 카테고리의 다른 글

피보나치 수(Fibonacci number)이란?  (0) 2023.12.15
Posted by Scripter
,

피보나치 수열는 피보나치가 토끼의 성장과 번식을 관찰하다가 발견한 수열이라고 합니다.

피보나치 수(Fibonacci number)의 정의는 간단합니다.

0과 1로 시작해서 덧셈을 계속 이어가면 얻어지는 수들입니다.

     0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ......

초항을 제 0항으로 하고 제 0항, 제 1항, 제 2항, ...... 순으로 나열하면

    F(0),  F(1),  F(2),  F(3),  F(4), F(5),  F(6),  F(7),  F(8),  F(9),  F(10), ......

이 되고, 번호를 괄호 속에 넣지 않고 우측 첨자로 붙여 나열하면,

    F0,  F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, ......

이 됩니다.  즉, 

                  F0 = F(0) = 0

                  F1 = F(1) = 1

                  F2 = F(2) = 1

                  F3 = F(3) = 2

                  F4 = F(4) = 3

                  F5 = F(5) = 5

                  F6 = F(6) = 8

                  F7 = F(7) = 13

                  F8 = F(8) = 21

                  F9 = F(9) = 34

                  F10 = F(10) = 55

                   ........................

피보나치 수들을 점화공식(recurrence formula)으로 정의하면

        F(n) = F(n - 1) + F(n - 2)     ∀ n = 2, 3, 4, 5, ...

        F(0) = 0,  F(1) = 1

가 됩니다.

            0 + 1 = 1

            1 + 1 = 2

            1 + 2 = 3

            2 + 3 = 5

            3 + 5 = 8

            5 + 8 = 13

             ..........

위의 점화공식  F(n) = F(n - 1) + F(n - 2)  은 

               F(n) - F(n - 1) = F(n - 2) 

혹은

               F(n) - F(n - 2) = F(n - 1) 

으로 사용되어지기도 합니다.

 

'알고리즘 > 피보나치' 카테고리의 다른 글

네가보나치(Negabonacci) 란  (0) 2023.12.15
Posted by Scripter
,

Java 에는 부호 없는 native 정수 타입이 없다.

Java 8에 와서야 부호 없는 정수를 처리하기 위한 메서드 몇 개가 추가되었다.

예를 들어, String을 native 타입 number로 변환하는 스태틱 메서드

        Long.parseUnsignedLong(String),  Integer.parseUnsignedint(String),

       Short.parseUnsignedShort(String),  Byte.parseUnsignedByte(String),

들과 역으로 native 타입 number를 String으로 변환하는 스태틱 메서드

        Long.toUnsignedString(long),  Integer.toUnsignedString(int)

가 있는데 이들은 타입 캐스팅할 댸 주의해야 할 부분이 있다.

아래의 Java 소스는 overflow 와 관련하여 심각한 문제가 발생할 수

있음을 보여 준다.

 

 

//  Filename: About_Java_Native_Number.java
//
//       Re-consider Java's native numbers (int or long or double) near to theirs maximal valuea
//
//
//  Compile: javac -d . About_Java_Native_Number.java
//  Execute: java About_Java_Native_Number
//
//
// Date: 2023.10.22


public class About_Java_Native_Number
{

    public static void main(String[] args)
    { 
        System.out.printf("What is pow(2, 30) = 2**30 (using Python's integer power operator expression)\n");
        System.out.printf("                   = 1 << 30 (using intege's shift opertor expression)\n");
        System.out.printf("                   = 2^30 (in LaTeX' math expression)\n");
        System.out.printf("\n");

        System.out.printf("Math.pow(2, 30) == %s\n", Math.pow(2, 30));
        System.out.printf("Math.pow(2, 30) == %e\n", Math.pow(2, 30));
        System.out.printf("Math.pow(2, 30) == %.9e\n", Math.pow(2, 30));
        System.out.printf("Math.pow(2, 30) == %g\n", Math.pow(2, 30));
        System.out.printf("Math.pow(2, 30) == %.0g\n", Math.pow(2, 30));
        System.out.printf("Math.pow(2, 30) == %.9g\n", Math.pow(2, 30));
        System.out.printf("Math.pow(2, 30) == %f\n", Math.pow(2, 30));
        System.out.printf("Math.pow(2, 30) == %.0f\n", Math.pow(2, 30));
        System.out.printf("Math.pow(2, 30) == %a\n", Math.pow(2, 30));
        System.out.printf("\n");

        System.out.printf("1 << 30 = %d\n", 1 << 30);
        System.out.printf("(1 << 30) + (1 << 30) = %d\n", (1 << 30) + (1 << 30) );
        System.out.printf("(1 << 30)*2 = %d\n", (1 << 30)*2);
        System.out.printf("1 << (1 << 30) << 1 = %d\n", (1 << 30) << 1 );
        System.out.printf("0x7FFFFFFF = %d\n", 0x7FFFFFFF);
        System.out.printf("0x7FFFFFFF + 1 = %d\n", 0x7FFFFFFF + 1);
        System.out.printf("0x7FFFFFFF + 2 = %d\n", 0x7FFFFFFF + 2);
        System.out.printf("0x7FFFFFFF + 2 = %d\n", 0x7FFFFFFF + 2);
        System.out.printf("0x7FFFFFFF + 1 - 1 = %d\n", 0x7FFFFFFF + 1 - 1);
        System.out.printf("0x7FFFFFFF + 2 - 2 = %d\n", 0x7FFFFFFF + 2 - 2);
        System.out.printf("0x7FFFFFFF + 3 - 3 = %d\n", 0x7FFFFFFF + 3 - 3);
        System.out.printf("\n");

        System.out.printf("Is it true that (0x7FFFFFFF + 1) - 1 = (%d + 1) - 1 = %d - 1 = %d ?\n", 0x7FFFFFFF, 0x7FFFFFFF + 1, (0x7FFFFFFF + 1) - 1);
        System.out.printf("Is it true that (0x7FFFFFFF + 2) - 2 = (%d + 2) - 2 = %d - 2 = %d ?\n", 0x7FFFFFFF, 0x7FFFFFFF + 2, (0x7FFFFFFF + 1) - 2);
        System.out.printf("Is it true that (0x7FFFFFFF + 3) - 3 = (%d + 3) - 3 = %d - 3 = %d ?\n", 0x7FFFFFFF, 0x7FFFFFFF + 3, (0x7FFFFFFF + 1) - 3);
        System.out.printf("\n");

        System.out.printf("It is true that 1 << 30 = %d\n", 1 << 30);
        System.out.printf("But, is it true that (1 << 30)*2/2 = (%d)*2/2 = %d/2 = %d ?\n", 1 << 30, (1 << 30)*2,  (1 << 30)*2/2);
        System.out.printf("And, is it true that (1 << 30)*2/4 = (%d)*2/4 = %d/4 = %d ?\n", 1 << 30, (1 << 30)*2,  (1 << 30)*2/4);
        System.out.printf("And, is it true that (1 << 30)*2/8 = (%d)*2/8 = %d/8 = %d ?\n", 1 << 30, (1 << 30)*2,  (1 << 30)*2/8);
        System.out.printf("\n");

        System.out.printf("Also, is it true that (1 << 30)*4/2 = (%d)*4/2 = %d/2 = %d ?\n", 1 << 30, (1 << 30)*4,  (1 << 30)*4/2);
        System.out.printf("Also, is it true that ((1 << 30)*4 + 1234567)/2 = ((%d)*4 + 1234567)/2 = (%d + 1234567)/2 = %d ?\n", 1 << 30, (1 << 30)*4,  ((1 << 30)*4 + 1234567)/2);
        System.out.printf("Then, is it true that (Math.pow(2, 30)*4 + 1234567)/2 = ((%.0f)*4 + 1234567)/2 = (%.0f + 1234567)/2 = %.0f ?\n", Math.pow(2, 30), Math.pow(2, 30)*4,  (Math.pow(2, 30)*4 + 1234567)/2);


        System.out.printf("In is known that Math.pow(2, 30) == (1 << 30) ? %s\n", Math.pow(2, 30) == (1 << 30));
        System.out.printf("\n");

        System.out.printf("Long.toUnsignedString((byte)0xFFL) = %s\n", Long.toUnsignedString((byte)0xFFL));
        System.out.printf("Long.toUnsignedString(0xFFL) = %s\n", Long.toUnsignedString(0xFFL));
        System.out.printf("Integer.toUnsignedString((byte)0xFFL) = %s\n", Integer.toUnsignedString((byte)0xFFL));
        System.out.printf("Integer.toUnsignedString(0xFF) = %s\n", Integer.toUnsignedString(0xFF));
        System.out.printf("Integer.toUnsignedString(0xFFFFFFFFFF) = %s\n", Integer.toUnsignedString(0xFFFFFFFF));
        System.out.printf("Long.toUnsignedString(0xFFFFFFFFFF) = %s\n", Long.toUnsignedString(0xFFFFFFFF));
        System.out.printf("Long.toUnsignedString(0x100000000L) = %s\n", Long.toUnsignedString(0x100000000L));
        System.out.printf("Long.toUnsignedString(0xFFFFFFFFFFFFFFFFL) = %s\n", Long.toUnsignedString(0xFFFFFFFFFFFFFFFFL));
        System.out.printf("Long.toUnsignedString(0x8000000000000000L) = %s\n", Long.toUnsignedString(0x8000000000000000L));
        System.out.printf("Long.toString(0xFFFFFFFFFFFFFFFFL) = %s\n", Long.toString(0xFFFFFFFFFFFFFFFFL));
        System.out.printf("Long.toString(0x8000000000000000L) = %s\n", Long.toString(0x8000000000000000L));
        System.out.printf("\n");

    }
}

/*
---------
 Output:
---------

What is pow(2, 30) = 2**30 (using Python's integer power operator expression)
                   = 1 << 30 (using intege's shift opertor expression)
                   = 2^30 (in LaTeX' math expression)

Math.pow(2, 30) == 1.073741824E9
Math.pow(2, 30) == 1.073742e+09
Math.pow(2, 30) == 1.073741824e+09
Math.pow(2, 30) == 1.07374e+09
Math.pow(2, 30) == 1e+09
Math.pow(2, 30) == 1.07374182e+09
Math.pow(2, 30) == 1073741824.000000
Math.pow(2, 30) == 1073741824
Math.pow(2, 30) == 0x1.0p30

1 << 30 = 1073741824
(1 << 30) + (1 << 30) = -2147483648
(1 << 30)*2 = -2147483648
1 << (1 << 30) << 1 = -2147483648
0x7FFFFFFF = 2147483647
0x7FFFFFFF + 1 = -2147483648
0x7FFFFFFF + 2 = -2147483647
0x7FFFFFFF + 2 = -2147483647
0x7FFFFFFF + 1 - 1 = 2147483647
0x7FFFFFFF + 2 - 2 = 2147483647
0x7FFFFFFF + 3 - 3 = 2147483647

Is it true that (0x7FFFFFFF + 1) - 1 = (2147483647 + 1) - 1 = -2147483648 - 1 = 2147483647 ?
Is it true that (0x7FFFFFFF + 2) - 2 = (2147483647 + 2) - 2 = -2147483647 - 2 = 2147483646 ?
Is it true that (0x7FFFFFFF + 3) - 3 = (2147483647 + 3) - 3 = -2147483646 - 3 = 2147483645 ?

It is true that 1 << 30 = 1073741824
But, is it true that (1 << 30)*2/2 = (1073741824)*2/2 = -2147483648/2 = -1073741824 ?
And, is it true that (1 << 30)*2/4 = (1073741824)*2/4 = -2147483648/4 = -536870912 ?
And, is it true that (1 << 30)*2/8 = (1073741824)*2/8 = -2147483648/8 = -268435456 ?

Also, is it true that (1 << 30)*4/2 = (1073741824)*4/2 = 0/2 = 0 ?
Also, is it true that ((1 << 30)*4 + 1234567)/2 = ((1073741824)*4 + 1234567)/2 = (0 + 1234567)/2 = 617283 ?
Then, is it true that (Math.pow(2, 30)*4 + 1234567)/2 = ((1073741824)*4 + 1234567)/2 = (4294967296 + 1234567)/2 = 2148100932 ?
In is known that Math.pow(2, 30) == (1 << 30) ? true

Long.toUnsignedString((byte)0xFFL) = 18446744073709551615
Long.toUnsignedString(0xFFL) = 255
Integer.toUnsignedString((byte)0xFFL) = 4294967295
Integer.toUnsignedString(0xFF) = 255
Integer.toUnsignedString(0xFFFFFFFFFF) = 4294967295
Long.toUnsignedString(0xFFFFFFFFFF) = 18446744073709551615
Long.toUnsignedString(0x100000000L) = 4294967296
Long.toUnsignedString(0xFFFFFFFFFFFFFFFFL) = 18446744073709551615
Long.toUnsignedString(0x8000000000000000L) = 9223372036854775808
Long.toString(0xFFFFFFFFFFFFFFFFL) = -1
Long.toString(0x8000000000000000L) = -9223372036854775808
*/

 

 

 

 

Posted by Scripter
,

정수부의 자리수가 조금 큰 부동소수점수(64비트 double 포맷의 수)를 십진수 표현으로 출력해 보았습니다.

십진수로 표현하면  유효자리수 개수가 약 14~15개 정도인데,

Java 언어와 C# 언어에서는 유효수자를 적당한 개수(17개나 15개)로 자르고

그 뒤를 모두 0으로 출력하였지만,

C++ 언어에서는 유효수자 아래 부분을 자르지 않고 모두 출력합니다.

Pyhon, Ruby 언어에서도 C/C++ 언어 처럼 유효수자 아래 부분을 0으로 채우지 않습니다.

 

물론 Java, C#, Python, C, C++ 어느 프로그램 언어든

십진수로 표현할 때 자르는 방법이나 유효수자 아래 부분을 채우는 방법은 다르지만,

덧셈, 뺄셈, 곱셈, 나누셈, 기타 등등에서 유효수자 아래부분의 처리 결과는 대동소이합니다.

 

C++ 언어에서 긴 자리 정수를 처리하기 위해

gmplib 를 Visual C/C++ 용으로 개조한  mpir 라이브러리를 사용하였습니다.

 

// Filename: Test_Of_Native_Double_CPP_01.cpp
//
//
// Compile: cl /utf-8 /EHsc /I. Test_Of_Native_Double_CPP_01.cpp mpir.lib mpirxx.lib
// Execute: Test_Of_Native_Double_CPP_01
// Output:
//                            pow(2, 128) = 340282366920938463463374607431768211456.000000
//                            pow(2, 128) = 340282366920938463463374607431768211456
//     After mpz_pow(r, 2, 128), we get r = 340282366920938463463374607431768211456
//     Let b = 18446744073709551616 = 0x10000000000000000
//     Then we get b * b = 340282366920938463463374607431768211456 = 0x100000000000000000000000000000000
//
//
//  ------------------------------------------------------
//  출처: https://scripting.tistory.com/
//  ------------------------------------------------------


#include <cstdio>
#include <cmath>

#include <mpir.h>
#include <mpirxx.h>

#include <iostream>


using namespace std;

void test_01() 
{
      double y = pow(2, 128);
      printf("                       pow(2, 128) = %f\n", y);
      printf("                       pow(2, 128) = %.f\n", y);
         
    
    mpz_t r, a;

    mpz_init (r);
    mpz_init_set_str(a, "2", 0);

    mpz_pow_ui(r, a, 128);

    gmp_printf("After mpz_pow(r, %Zd, 128), we get r = %Zd\n", a, r);


    mpz_clear(r);
    mpz_clear(a);
    
    mpz_class b, c;


    b = "0x10000000000000000";
    c = b * b;

    cout << "Let b = " << b << " = " << hex << showbase << b << dec << noshowbase << endl;
    cout << "Then we get b * b = " << c << " = " << hex << showbase << c << dec << noshowbase << endl;

                  
}
    
int main(int argc, const char *argv[])
{
    test_01();
    printf("\n");
}

 

 

 

Posted by Scripter
,

정수부의 자리수가 조금 큰 부동소수점수(64비트 double 포맷의 수)를 십진수 표현으로 출력해 보았습니다.

십진수로 표현하면  유효자리수 개수가 약 14~15개 정도인데,

Java 언어와 C# 언어에서는 유효수자 개수로 자르고 그 뒤를 모두 0으로 출력지만,

Ruby 언어에서는 Python, C/C++ 언어들 처럼 유효수자 아래 부분을 자르지 않고 모두 츨력합니다.

 

물론 Java, C#, Python, C, C++ 어느 프로그램 언어든

십진수로 표현할 때 자르는 방법이나 유효수자 아래 부분을 채우는 방법은 다르지만,

덧셈, 뺄셈, 곱셈, 나누셈, 기타 등등에서 유효수자 아래부분의 처리 결과는 대동소이합니다.

 

 

 

# -*- coding: utf-8 -*-
#
# Filename: Test_Of_Native_Double_Precison_01.rb
#
#
# Execute: ruby Test_Of_Native_Double_Precison_01.rb
# Output:
#            2.pow(128) = 340282366920938463463374607431768211456.000000
#            2.pow(128) = 340282366920938463463374607431768211456
#                2**128 = 340282366920938463463374607431768211456
#         2**64 * 2**64 = 340282366920938463463374607431768211456
#
#
#  ------------------------------------------------------
#  출처: https://scripting.tistory.com/
#  ------------------------------------------------------


def test_01()
    y = 2.pow(128)
    print("       2.pow(128) = %f\n" % y)
    print("       2.pow(128) = %.f\n"% y)

    z = 2**128
    print("           2**128 = %d\n" % z)
    print("    2**64 * 2**64 = %d\n" % (2**64 * 2**64))
end
    

test_01()
print

 

 

Posted by Scripter
,

정수부의 자리수가 조금 큰 부동소수점수(64비트 double 포맷의 수)를 십진수 표현으로 출력해 보았습니다.

십진수로 표현하면  유효자리수 개수가 약 14~15개 정도인데,

Java 언어와 C# 언어에서는 유효수자를 적당한개수(17개나 15개)로 자르고

그 뒤를 모두 0으로 출력하였지만,

C 언어에서는 유효수자 아래 부분을 자르지 않고 모두 출력합니다.

Pyhon 언어에서도 C 언어 처럼 유효수자 아래 부분을 0으로 채우지 않습니다.

 

물론 Java, C#, Python, C, C++ 어느 프로그램 언어든

십진수로 표현할 때 자르는 방법이나 유효수자 아래 부분을 채우는 방법은 다르지만,

덧셈, 뺄셈, 곱셈, 나누셈, 기타 등등에서 유효수자 아래부분의 처리 결과는 대동소이합니다.

 

C 언어에서 긴 자리 정수를 처리하기 위해

gmplib 를 Visual C/C++ 용으로 개조한  mpir 라이브러리를 사용하였습니다.

 

// Filename: Test_Of_Native_Double_01.c
//
//
// Compile: cl /utf-8 /EHsc /I. Test_Of_Native_Double_01.c mpir.lib
// Execute: Test_Of_Native_Double_01
// Output:
//                            pow(2, 128) = 340282366920938463463374607431768211456.000000
//                            pow(2, 128) = 340282366920938463463374607431768211456
//     After mpz_pow(r, 2, 128), we get r = 340282366920938463463374607431768211456
//
//
//  ------------------------------------------------------
//  출처: https://scripting.tistory.com/
//  ------------------------------------------------------


#include <stdio.h>
#include <math.h>

#include <mpir.h>


void test_01() 
{
      double y = pow(2, 128);
      printf("                       pow(2, 128) = %f\n", y);
      printf("                       pow(2, 128) = %.f\n", y);        
    
    mpz_t r, a;

    mpz_init (r);
    mpz_init_set_str(a, "2", 0);

    mpz_pow_ui(r, a, 128);

    gmp_printf("After mpz_pow(r, %Zd, 128), we get r = %Zd\n", a, r);


    mpz_clear(r);
    mpz_clear(a);
                  
}
    
int main(int argc, const char *argv[])
{
    test_01();
    printf("\n");
}

 

 

 

Posted by Scripter
,

정수부의 자리수가 조금 큰 부동소수점수(64비트 double 포맷의 수)를 십진수 표현으로 출력해 보았습니다.

십진수로 표현하면  유효자리수 개수가 약 14~15개 정도인데,

Java 언어로는 유효수자 개수를 17개로 자르고 그 뒤를 모두 0으로 출력하였지만,

C# 언어로는 유효수자 아래 부분을 15개로 자르고 그 뒤를 모두 0으로 출력합니다.

Pyhon 은 C/C++ 의 경우 처럼 유효수자 아래 부분을 0으로 채우지 않습니다.

 

물론 Java, C#, Python, C, C++ 어느 프로그램 언어든

십진수로 표현할 때 자르는 방법이나 유효수자 아래 부분을 채우는 방법은 다르지만,

덧셈, 뺄셈, 곱셈, 나누셈, 기타 등등에서 유효수자 아래부분의 처리 결과는 대동소이합니다.

 

 

// Filename: Test_Of_Native_Double_Precison_01.cs
//
//
// Compile: csc Test_Of_Native_Double_Precison_01.cs /r:System.Numerics.dll
// Execute: Test_Of_Native_Double_Precison_01
// Output:
//                          Math.Pow(2, 128) = 340282366920938000000000000000000000000.00
//                          Math.Pow(2, 128) = 340282366920938000000000000000000000000
//     BigInteger.Pow(new BigInteger(2).128) = 340282366920938463463374607431768211456
//
//
//  ------------------------------------------------------
//  출처: https://scripting.tistory.com/
//  ------------------------------------------------------


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Collections;
using System.Numerics;


public class Test_Program_Of_Native_Double
{
    public static void Test_01() 
    {
          double y = Math.Pow(2, 128);
          Console.WriteLine("                     Math.Pow(2, 128) = {0:F}", y);
          Console.WriteLine("                     Math.Pow(2, 128) = {0:F0}", y);

          BigInteger z = BigInteger.Pow(new BigInteger(2), 128);
          Console.WriteLine("BigInteger.Pow(new BigInteger(2).128) = {0}", z);
    }
    
    public static void Main(string[] args)
    {
        Test_01();
        Console.WriteLine();
    }
}

 

 

 

Posted by Scripter
,