정수부의 자리수가 조금 큰 부동소수점수(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
,

 

아래의 단순한 코드로 작성되어 gcc 로 컴파일된 실행파일의 콘솔 출력이 비정상인 경우....

 

#include <stdio.h>

int main(void)
{
    int i;

    for (i = 0; i < 5; i++)
    {
        printf("abcd %d\r\n",i);
        Sleep(1000);
    }
    return 0;
}

 

첫째 해결 방법:

    아래의 수정된 코드 처럼 모든 printf.(...);  구문 뒤에 fflush(strout); 를 추가한다.

#include <stdio.h>

int main(void)
{
    int i;

    for (i = 0; i < 5; i++)
    {
        printf("abcd %d\r\n",i);
        fflush(stdout);     // 모든 printf(...); 구문 뒤에 이를 추가한다.
        
        Sleep(1000);
    }
    return 0;
}

 

둘째 해결 방법:

    아래의 수정된 코드 처럼 모든 main() 함수에서

     printf(...);  구문이 시작되기 전에 setvbuf(...);  구문을 한 번만 추가한다.

#include <stdio.h>

int main(void)
{
    int i;

    setvbuf(stdout, (char *)NULL, _IOLBF,0 );

    for (i = 0; i < 5; i++)
    {
        printf("abcd %d\r\n",i);
        Sleep(1000);
    }
    return 0;
}

 

※ 윈도우의 MSYS2 에서 flex & bison 으로 작성된 어플의 printf() 출력이 제대로 안 될 때는

  위의 두 가지 방법 모두 안 되니, 다른 방법으로 해결해여 한다.

 

 

 

Posted by Scripter
,

 

 

아래의 소스는

Coefficients for the Lanczos Approximation to the Gamma Function

의 것을 Microsoft Visual C/C++ 명령줄 컴파일러 cl 로 컴파일되도록 수정한 것이다.

 

// Filename: test_gamma_lanczos.c
//
// Compile: cl test_gamma_lanczos.c /EHsc /utf-8
// Execute: test_gamma_lanczos

#include <stdio.h>
	
#define _USE_MATH_DEFINES // for C
#include <math.h>
	
  #define LG_g 5.0      // Lanczos parameter "g"
  #define LG_N 6        // Range of coefficients i=[0..N]
  const double lct[LG_N+1] = {
     1.000000000190015,
    76.18009172947146,
   -86.50532032941677,
    24.01409824083091,
    -1.231739572450155,
     0.1208650973866179e-2,
    -0.5395239384953e-5
  };

  const double ln_sqrt_2_pi = 0.91893853320467274178;
  const double         g_pi = 3.14159265358979323846;

  double lanczos_ln_gamma(double z)
  {
    double sum;
    double base;
    double rv;
    int i;
    
    if (z < 0.5) {
      return log(g_pi / sin(g_pi * z)) - lanczos_ln_gamma(1.0 - z);
    }
    z = z - 1.0;
    base = z + LG_g + 0.5;  // Base of the Lanczos exponential
    sum = 0;

    for(i=LG_N; i>=1; i--) {
      sum += lct[i] / (z + ((double) i));
    }
    sum += lct[0];
    return ((ln_sqrt_2_pi + log(sum)) - base) + log(base)*(z+0.5);
  }

  double lanczos_gamma(double z)
  {
    return(exp(lanczos_ln_gamma(z)));
  }
  
  int main()
  {
      printf("                        Gamma(0.5)               Log(Gamma(0.5))\n");
      printf("                 ---------------------------------------------------\n");
      printf("  Lanczos Gamma: %22.18f     %22.18f\n", lanczos_gamma(0.5), lanczos_ln_gamma(0.5));
      printf("       Built-in: %22.18f     %22.18f\n", exp(lgamma(0.5)), lgamma(0.5));
      printf("   Use sqrt(PI): %22.18f     %22.18f\n", sqrt(M_PI), log(sqrt(M_PI)));

      return 0;	  
  }

 

 

빌트인 Gamma 함수와 비교하여 12자리 까지만 맞는데,

이는 허용오차가 약 sqrt(PI)*N 이기 때문이다.

여기서 N은 Lanczos 계수의 개수이다, (소스에서는 LG_N+1)

Python 인터프러터를 실행하여 잠깐 그 허용오차를 알아본다.

Python 3.7.5 
>>> import math
>>> math.gamma(0.5)
1.7724538509055159
>>> import math
>>> math.sqrt(math.pi)*7
12.407176956338612

N=7 인 경우, 유효수자의 개수는 약 12개이다.

 

 

 

 

 

 

 

 

 

Posted by Scripter
,

Visual Studio 2019 와 MSYS2 MinGW64 에서 테스트 된 소스입니다.

 혹시 MinGW 에서 컴파일되지 않으면

$ packman -S mpfr

명령으로 mpfr 라이브러리를 설치하고 컴파일하면 된다.

 

// Filename: calcGammaFn.c
//
// Compile: gcc -o calcGammaFn calcGammaFn.c -lmpfr -lgmp
// Execute: ./calcGammaFn
//     Or
// Compile: cl calcGammaFn.c /I. mpfr.lib
// Execute: calcGammaFn
//
// Date: 2021.01.28


#include <stdio.h>
#include <math.h>    // for log(10)
#include <mpfr.h>

int main()
{
  mpfr_t x; 
  int i, inex;

  mpfr_set_emin (-41);
  mpfr_init2 (x, 42);

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_gamma (x, x, MPFR_RNDZ);      
      mpfr_subnormalize (x, inex, MPFR_RNDZ);
      mpfr_dump (x);
  }

  printf("\n");

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_gamma (x, x, MPFR_RNDZ);
      mpfr_printf("Gamma(%2d) = %2d! = %Rf\n", i, i - 1, x);
  }

  printf("\n");

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_lngamma (x, x, MPFR_RNDZ);
      mpfr_printf("LogGamma(%2d) = Log(%2d!) = %Rf\n", i, i - 1, x);
  }

  printf("\n");

 double t10 = log(10.0);
 printf("log(10) = %f\n", t10);
 
  printf("\n");

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_lngamma (x, x, MPFR_RNDZ);      
      inex = mpfr_div_d(x, x, t10,  MPFR_RNDZ);
      mpfr_printf("Log10Gamma(%2d) = Log10(%2d!) = %Rf\n", i, i - 1, x);
  }

  mpfr_clear (x);
  
  return 0;
}

/*
Output:
LogGamma( 1) = Log( 0!) = 0
LogGamma( 2) = Log( 1!) = 0
LogGamma( 3) = Log( 2!) = 0.693147
LogGamma( 4) = Log( 3!) = 1.791759
LogGamma( 5) = Log( 4!) = 3.178054
LogGamma( 6) = Log( 5!) = 4.787492
LogGamma( 7) = Log( 6!) = 6.579251
LogGamma( 8) = Log( 7!) = 8.525161
LogGamma( 9) = Log( 8!) = 10.604603
LogGamma(10) = Log( 9!) = 12.801827
LogGamma(11) = Log(10!) = 15.104413
LogGamma(12) = Log(11!) = 17.502308
LogGamma(13) = Log(12!) = 19.987214
LogGamma(14) = Log(13!) = 22.552164
LogGamma(15) = Log(14!) = 25.191221
LogGamma(16) = Log(15!) = 27.899271
LogGamma(17) = Log(16!) = 30.671860

log(10) = 2.302585

Log10Gamma( 1) = Log10( 0!) = 0
Log10Gamma( 2) = Log10( 1!) = 0
Log10Gamma( 3) = Log10( 2!) = 0.301030
Log10Gamma( 4) = Log10( 3!) = 0.778151
Log10Gamma( 5) = Log10( 4!) = 1.380211
Log10Gamma( 6) = Log10( 5!) = 2.079181
Log10Gamma( 7) = Log10( 6!) = 2.857332
Log10Gamma( 8) = Log10( 7!) = 3.702431
Log10Gamma( 9) = Log10( 8!) = 4.605521
Log10Gamma(10) = Log10( 9!) = 5.559763
Log10Gamma(11) = Log10(10!) = 6.559763
Log10Gamma(12) = Log10(11!) = 7.601156
Log10Gamma(13) = Log10(12!) = 8.680337
Log10Gamma(14) = Log10(13!) = 9.794280
Log10Gamma(15) = Log10(14!) = 10.940408
Log10Gamma(16) = Log10(15!) = 12.116500
Log10Gamma(17) = Log10(16!) = 13.320620
*/

 

 

 

 

 

Posted by Scripter
,

Cygwin 에서는 printf 와 wprint 를 동시에 사용하는 경우, 컴파일은 성공하지만 실행하면 wprintf 가 제대로 동작하지 않는다.  그리고 wprint 나 swptinf 사용 시 스트링을 출력하기 위해서는 %s 대신 %ls 포맷을 사용해야 한다.

Cygwin 의 경우 wchar_t 의 크기는 2바이트이다.

 

#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <locale.h>

int main(int argc, const char *argv[]) {
    wchar_t wt[100];

    /// setlocale(LC_ALL,"kr_KR.UTF-8");
    setlocale(LC_ALL,"");
    // printf("sizeof(wchar_t) = %d\n", sizeof(wchar_t));
    // printf("For more informations, \nsee: http://www.firstobject.com/wchar_t-string-on-linux-osx-windows.htm\n");

    wprintf(L"sizeof(wchar_t) = %d\n", sizeof(wchar_t));
    wprintf(L"For more informations, \nsee: http://www.firstobject.com/wchar_t-string-on-linux-osx-windows.htm\n");

    wprintf(L"\n");
    wcscpy(wt, L"abc 가나다");
    wprintf(L"%ls\n", wt);
    swprintf(wt, wcslen(L"abc 가나다") + 1, L"%ls", L"abc 가나다");
    wprintf(L"%ls\n", wt);
    wprintf(L"%ls\n", L"abc 가나다");
    wprintf(L"abc 가나다\n");

    return 0;
}

 

컴파일:

$ gcc -o testWcharT_02 testWcharT_02.c

실행:

$ ./testWchaTr_02

sizeof(wchar_t) = 2
For more informations,
see: http://www.firstobject.com/wchar_t-string-on-linux-osx-windows.htm

abc 가나다
abc 가나다
abc 가나다
abc 가나다

 

 

 

 

Posted by Scripter
,

우선 다음은 ms949 인코딩으로 저장한 C 소스이다.

* 소스 파일명: hello.c

#include <stdio.h>
#include <string.h>

int main()
{
    printf("Hello, 안녕하세요?\n");
    printf("strlen(\"Hello, 안녕하세요?\\n\") = %d\n", strlen("Hello, 안녕하세요?\n"));

 return 0;
}

* 컴파일

> gcc -o hello hello.c

*

 실행

> hello

Hello, 안녕하세요?
strlen("Hello, 안녕하세요?\n") = 19

 

다음은 utf-8 인코딩으로 저장한 C 소스이다.

* 소스 파일명: hello2.c

#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <locale.h>

#define wstrlen wcslen

int main()
{
    setlocale(LC_ALL,"");

    printf("Using strlen():\n");
    printf("Hello, 안녕하세요?\n");
    printf("strlen(\"Hello, 안녕하세요?\\n\") = %d\n", strlen("Hello, 안녕하세요?\n"));

    wprintf(L"Using wcslen():\n");
 wprintf(L"Hello, 안녕하세요?\n");
    wprintf(L"wstrlen(\"Hello, 안녕하세요?\\n\") = %d\n", wstrlen(L"Hello, 안녕하세요?\n"));

 return 0;
}

* 컴파일

> gcc -o hello2 hello2.c

* 실행

> hello2

Using strlen():
Hello, ?덈뀞?섏꽭??
strlen("Hello, ?덈뀞?섏꽭??\n") = 24
Using wcslen():
Hello, 안녕하세요?
wstrlen("Hello, 안녕하세요?\n") = 14

 

다음도 utf-8 인코딩으로 저장한 C 소스이다.

* 소스 파일명: hello3.c

#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <locale.h>

#define wstrlen wcslen

int main()
{
 char as[] = "Hello, 안녕하세요?";
 wchar_t bs[] = L"Hello, 안녕하세요?";

 setlocale(LC_ALL,"");

    printf("Using strlen():\n");
    printf("Hello, 안녕하세요?\n");
    printf("strlen(\"Hello, 안녕하세요?\\n\") = %d\n", strlen("Hello, 안녕하세요?\n"));
    printf("strlen(\"%s\") = %d\n", as, strlen(as));
    printf("\n");

    wprintf(L"Using wcslen():\n");
 wprintf(L"Hello, 안녕하세요?\n");
    wprintf(L"wstrlen(\"Hello, 안녕하세요?\\n\") = %d\n", wstrlen(L"Hello, 안녕하세요?\n"));
    wprintf(L"wstrlen(\"%s\") = %d\n", bs, wstrlen(bs));

 return 0;
}

* 컴파일

> gcc -o hello3 hello3.c

* 실행

> hello3

Using strlen():
Hello, ?덈뀞?섏꽭??
strlen("Hello, ?덈뀞?섏꽭??\n") = 24
strlen("Hello, ?덈뀞?섏꽭??") = 23

Using wcslen():
Hello, 안녕하세요?
wstrlen("Hello, 안녕하세요?\n") = 14
wstrlen("Hello, 안녕하세요?") = 13

 

 

Posted by Scripter
,

pdcurses 를 컴파일하여 Visual C++ 용 라이브러리 만들기

프롬프트> nmake -f vcwin32.mak

 

* 테스트용 소스 파일:  helloworld.c (http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/helloworld.html 에 있는 ncurses 용 소스에서 인클루드 문의 ncurses.h 를 curses.h 로 변경한 것 뿐임)

/*
 * Filename: helloworld.c
 *
 * Compile: cl /c helloworld.c /I .
 *       Link: link -nologo helloworld.obj pdcurses.lib user32.lib gdi32.lib advapi32.lib shell32.lib comdlg32.lib
*   Or
 * Compile & Link: cl helloworld.c -I . pdcurses.lib user32.lib gdi32.lib shell32.lib comdlg32.lib
 *
 * Execute: helloworld
 *
 * Date: 2014. 1. 15.
 */

#include <curses.h>           /* changed from <ncurses.h> */

int main()

    initscr();                          /* Start curses mode     */


    printw("Hello World !!!");    /* Print Hello World    */
    refresh();                         /* Print it on to the real screen */
    getch();                          /* Wait for user input */

    endwin();                        /* End curses mode    */

    return 0;
}

 

* 실행 결과:

 

 

 

Posted by Scripter
,

ncurses(또는 curses) 는 Linux/Unix 계열의 환경에서 VT100 등의 터미널과 호환되는 윈도우형 입출력 라이브러이다. 이를 이용하면 윈도우의 임의의 위치에 출력도 하고, 임의의 위치에서 입력을 받을 수도 있다.

* 카라슈바 곱셈 참조

다음은 Linux 나 Cygwin 환경이면 gcc 로 컴파일하여 실행되는 C 소스이다.

 

/*
 * Filename: ezmult_003.c
 *
 * Compile: gcc -o ezmult_003 ezmult_003.c -lform -lncurses
 *
 * Execute: ./ezmult_003
 *
 *    Date: 2014. 1. 6. (Mon)  v0.002
 *    Date: 2014. 1. 8. (Wed)  v0.003
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <form.h>
#include <ncurses.h>

int main()
{
    int x0, y0, z0;
    int s01, s02, t0;
    int x, y, z;
    int s1, s2, t;
    int i, j;
    int flag_insert_mode = 1;
    int o1 = 0;
    int o2 = 0;
    int o3 = 0;

    FIELD *field[4];
    FORM  *my_form;
    int ch;
 
    /* curses 초기화하기 */
    initscr();
    start_color();    // 색상을 사용하려면 initscr() 호출 후 즉시 이를 호출해야 함
    nonl();            // 필드에서 엔터 키가 작용되게 하기 위함
    cbreak();
    noecho();
    keypad(stdscr, TRUE);


    srand(time(NULL));
    x = rand()/(RAND_MAX + 1.0)*90 + 10;
    y = rand()/(RAND_MAX + 1.0)*90 + 10;
    z = x*y;
    s1 = (x/10)*(y/10);
    s2 = (x%10)*(y%10);
    t = (x/10)*(y%10) + (x%10)*(y/10);
   
    if (s1 < 10)
    {
         o1 = 1;
    }
    if (t < 100)
    {
         o2 = 1;
    }
    if (z < 1000)
    {
         o3 = 1;
    }
    refresh();
    

    /* 필드 초기화 */
    field[0] = new_field(1, 4-o1,  6, 14+o1, 0, 0);
    field[1] = new_field(1, 3-o2,  7, 14+o2, 0, 0);
    field[2] = new_field(1, 4-o3,  9, 14+o3, 0, 0);
    field[3] = NULL;


    /* 폼 생성하여 붙여 넣기 */
    my_form = new_form(field);
    post_form(my_form);
    refresh();


     /* 색상 초기화 */
    init_pair(1, COLOR_WHITE, COLOR_GREEN);
    init_pair(2, COLOR_WHITE, COLOR_GREEN);
    init_pair(3, COLOR_WHITE, COLOR_GREEN);
    init_pair(4, COLOR_MAGENTA, COLOR_BLACK);
    init_pair(5, COLOR_CYAN, COLOR_BLACK); 
    init_pair(6, COLOR_WHITE, COLOR_BLACK);
    init_pair(7, COLOR_BLACK, COLOR_WHITE);


    x0 = rand()/(RAND_MAX + 1.0)*90 + 10;
    y0 = rand()/(RAND_MAX + 1.0)*90 + 10;
    z0 = x0*y0;
    s01 = (x0/10)*(y0/10);
    s02 = (x0%10)*(y0%10);
    t0 = (x0/10)*(y0%10) + (x0%10)*(y0/10);


    mvprintw(3, 4, "%4d", x0);
    mvprintw(4, 3, "x%4d", y0);
    mvprintw(5, 3, "-----");
    mvprintw(6, 4, "%2d%02d", s01, s02);
    mvprintw(7, 4, "%3d", t0);
    mvprintw(8, 3, "-----");
    mvprintw(9, 4, "%4d", z0);
    refresh();


    mvprintw(3, 14, "%4d", x);
    mvprintw(4, 13, "x%4d", y);
    mvprintw(5, 13, "-----");
    mvprintw(8, 13, "-----");
    attron(COLOR_PAIR(7));
    mvprintw(0, 0, "Ins");
    attron(COLOR_PAIR(6));
    move(6, 14);
    refresh();


    set_field_type(field[0], TYPE_INTEGER, 0, 0, 9999);
    set_field_type(field[1], TYPE_INTEGER, 0, 0, 999);
    set_field_type(field[2], TYPE_INTEGER, 0, 0, 9999);
    field_opts_on(field[0], O_EDIT);
    field_opts_on(field[1], O_EDIT);
    field_opts_on(field[2], O_EDIT);
    field_opts_on(field[0], O_ACTIVE);
    field_opts_on(field[1], O_ACTIVE);
    field_opts_on(field[2], O_ACTIVE);

 
    /* 필드 옵션 설정 */
    set_field_back(field[0], A_UNDERLINE); 
    set_field_back(field[1], A_UNDERLINE); 

    set_field_back(field[2], A_UNDERLINE); 


    /* 필드 옵션 설정 */
    set_field_fore(field[0], COLOR_PAIR(1));
    set_field_back(field[0], COLOR_PAIR(2));
    set_field_fore(field[1], COLOR_PAIR(1));

    set_field_back(field[1], COLOR_PAIR(2));
    set_field_fore(field[2], COLOR_PAIR(1));
    set_field_back(field[2], COLOR_PAIR(2));


    if (s1 >= 10)
        move(6, 14);
    else
        move(6, 15);
    refresh();


    /* 사용자 요구에 따라 번복 여부 결정 */
    while((ch = getch()) != KEY_F(1) && ch != 0x1B && ch != 0x0D)   
        switch(ch)
      {

           case KEY_DOWN:
           case KEY_ENTER:
               /* 다음 필드로 가기 */
               form_driver(my_form, REQ_NEXT_FIELD);
               break;
          case KEY_UP:
              /* 이전 필드로 가기 */
              form_driver(my_form, REQ_PREV_FIELD);
              break;
         case KEY_BACKSPACE:
         case 0x7F:
              form_driver(my_form, REQ_DEL_PREV);
              break;
         case KEY_IC:
              if (flag_insert_mode != 0)
             {
                 form_driver(my_form, REQ_OVL_MODE);
                 getyx(stdscr, j, i);
                 mvprintw(0, 0, "   ");
                 move(j, i);
                 flag_insert_mode = 0;
             }
             else
            {
                 form_driver(my_form, REQ_INS_MODE);
                 getyx(stdscr, j, i);
                attron(COLOR_PAIR(7));
                mvprintw(0, 0, "Ins");
                attron(COLOR_PAIR(6));
                move(j, i);
                flag_insert_mode = 1;
            }
            break;
        case KEY_DC:
            form_driver(my_form, REQ_DEL_CHAR);
            break;
        case KEY_LEFT:
            form_driver(my_form, REQ_LEFT_CHAR);
            break;
        case KEY_RIGHT:
            form_driver(my_form, REQ_RIGHT_CHAR);
            break;
        default:
            form_driver(my_form, ch);
            break;
       }
    }
 
    form_driver(my_form, REQ_NEXT_FIELD);
 
    attron(COLOR_PAIR(6));
    mvprintw(13, 0, "You have answered");
    if (atoi(field_buffer(field[0], 0)) == s1*100 + s2)
         attron(COLOR_PAIR(5));
    else
         attron(COLOR_PAIR(4));
    mvprintw(14, 8, "%4d", atoi(field_buffer(field[0], 0)));
    if (atoi(field_buffer(field[1], 0)) == t)
         attron(COLOR_PAIR(5));
    else
         attron(COLOR_PAIR(4));
    mvprintw(15, 8, "%3d", atoi(field_buffer(field[1], 0)));
    if (atoi(field_buffer(field[2], 0)) == z)
         attron(COLOR_PAIR(5));
    else
         attron(COLOR_PAIR(4));
    mvprintw(16, 8, "%4d", atoi(field_buffer(field[2], 0)));

    attron(COLOR_PAIR(6));
    mvprintw(13, 20, "Right answer is");
    mvprintw(14, 28, "%2d%02d", s1, s2);
    mvprintw(15, 28, "%3d", t);
    mvprintw(16, 28, "%4d", z);
    if (atoi(field_buffer(field[0], 0)) == s1*100 + s2
         && atoi(field_buffer(field[1], 0)) == t
         && atoi(field_buffer(field[2], 0)) == z)
        mvprintw(18, 0, "    Your answer is right.");
    else
        mvprintw(18, 0, "    Your answer is wrong.");
    mvprintw(21, 0, "Press any key to quit...");
    getch();
   
    /* 폼을 떼어내고 메모리를 해제한다. */
    unpost_form(my_form);
    free_form(my_form);
    free_field(field[0]);
    free_field(field[1]);
    free_field(field[2]);

    endwin();

    return 0;
}
 

 

* 실행 결과:

 


 

Posted by Scripter
,

32bit OS 에서는 int 타입과 long 타입이 다 같이 4바이트의 크기를 갖지만.

64bit OS 에서는 int 타입이 4바이트, long 타입이 8바이트의 크기를 갖는다.

그렇다면 64비트 리눅스 환경에서 32비트 용으로 작성된 C 소스를 gcc 로 컴파일하려면 어떻게 해야 할까? 

 

// Filename: testIntSize.c

int main()
{
#include <stdio.h>

int main()
{
    printf("sizeof(int) = %d\n", sizeof(int));
    printf("sizeof(long) = %d\n", sizeof(long));

    return 0;
}

 

# 64비트 용으로 컴파일하고 실행하기

$ gcc -o testIntSize testIntSize.c

$ ./testIntSize

sizeof(int) = 4
sizeof(long) = 8

 

# 32비트 용으로 컴파일하고 실행하기 (옵션 -m32 추가)

$ gcc -m32 -o testIntSize testIntSize.c

$ ./testIntSize

sizeof(int) = 4
sizeof(long) = 4

 

 

Posted by Scripter
,

 

Visual C++ 2010 으로 컴파일할 경우, 헤더파일 inttypes.h 가 Visual C++ 2010 에는 빠져 있으므로 http://msinttypes.googlecode.com/svn/trunk/inttypes.h 를 가져와서 아래의 소스와 동일한 디렉토리에 두고 컴파일한다.

char * 타입의 C 스트링으로 부터 long long 타입의 정수로 파싱하려면 C99 에서 정한 함수 strtoll 함수를 쓰면 되는데 이 함수 역시 Visual C++ 2010 에는 빠져 있으므로, _strtoi64 함수로 대체하기 위해 소스의 앞 부분에 매크로 정의 #define strtoll _strtoi64 를 추가하였다.

또 main 함수 안에서 사용된 llabs 함수는 long long 타입의 정수의 절댓값을 구하는 함수이다. abs 함수를 쓰면 절댓값이 int 타입의 값으로 나오므로 long long 타입에 대하여는 잘못된 절댓값을 가져올 수 있다.

 

* gcc 4.6.* 또는 Visual Studio 2010 의 cl 로 컴파일되는 C 소스

/*
 * Filename: eulerPhiGoodC_01.c
 *
 *  Purpose:
 *          Calculate the Euler phi function of a given nonzero integer
 *          with using its muliplicative property.
 *
 *          The Euler phi function of a given positive integer n is defined as.
 *          the number of positive integers which are relative prime to n
 *          from 1 to n.
 *
 * Compile: gcc -o eulerPhiGoodC_01 eulerPhiGoodC_01.c
 *    Or
 * Compile: cl /DVC2010 eulerPhiGoodC_01.c
 *
 * Execute: ./eulerPhiGoodC_01 [nnn]
 *    Or
 * Execute: eulerPhiGoodC_01 [nnn]
 *
 *  Date: 2011. 11.  7 (Mon)    eulerPhiGoodPython_01.py
 *  Date: 2013. 12. 13 (Fri)    eulerPhiGoodC_01.c
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#ifdef VC2010
  #include "inttypes.h"
  #define strtoll _strtoi64
#else
  #include <inttypes.h>
#endif
 
void printUsage()
{
    printf("Usage: eulerPhiGoodC_01 [nnnnnn]\n");
    printf("nnnnnn should be an integer.\n");
}

long long gcd(long long a, long long b)
{
    long long a1 = abs(a);
    long long b1 = abs(b);
    long long q = a1;
    long long r = b1;
    long long t;
    while (r != 0)
    {
        t = r;
        r = q % r;
        q = t;
    }
    return q;
}

int divide_each(long long n)
{
    long long a = 3;

    if ((n & 0x1) == 0 || n <= 1)
        return 0;
    else if (n == 2)
        return 1;

    while (a*a <= n)
    {
        if ((n % a) == 0)
            return 0;
        a += 2;
    }
    
    return 1;
}

int is_prime(long long n)
{
    return divide_each(n);
}

long long next_prime(long long n)
{
    long long k = llabs(n);
   
    k = k + 1;
    if (k <= 2)
    {
        return 2LL;
    }

    if ((k % 2) == 0 && k > 2)
        k += 1;
    while (!is_prime(k))
        k += 2;

    return k;
}


 

int main(int argc, const char *argv[])
{
    long long n = 0;
    long long cnt = 0;
    long long nphi = 0;
    long long sum = 0;
    long long t = 0;
    long long g = 1;
    long long m = 0;
    long long p = 1;
    long long *factors = (long long *)malloc(sizeof(long long)*200);
    long long nfactor = 0;
    long long ndivisor = 1;   // the number of positive divisors of the input integer
    long long nsum = 1;       // the sum of all positive divisors of the input integer
    int ndx = 0;        // index of storing position factor in factors
    long long *divisors = NULL;
    long long last_prime;
    int i, j, k;

    if (argc != 2)
    {
        printUsage();
        exit(1);
    }
    else
    {
        n = strtoll(argv[1], NULL, 10);
        n = llabs(n);
        if (n != 0)
        {
            t = n;
            k = 0;
            m = 0;  // multiplicity of prime factor
            ndivisor = 1;   // the number of positive divisors of the input integer
            nsum = 1;       // the sum of all positive divisors of the input integer
            nphi = 1;       // the numner of positive integers relative prime to the input integer
    
            p = 1;
            while (t > 1 && p*p <= n)
            {
                p = next_prime(p);
                m = 0;
                while (t % p == 0)
                {
                    t = (long long)(t / p);
                    m = m + 1;
                }

                if (m > 0)
                {
                    factors[ndx] = p;
                    ndx += 1;
                    factors[ndx] = m;
                    ndx += 1;
                    nfactor += 1;
                    ndivisor *= (m + 1);
                    nsum *= (long long)((pow(p, m+1) - 1)/(p - 1));
                    nphi *= (long long)(pow(p, m - 1)*(p - 1));
                }
            }
    

            if (is_prime(t))
            {
                m = 1;
                factors[ndx] = t;
                ndx += 1;
                factors[ndx] = m;
                ndx += 1;
                nfactor += 1;
                ndivisor *= (m + 1);
                nsum *= (long long)((pow(t, m+1) - 1)/(t - 1));
                nphi *= (long long)pow(t, m - 1)*(t - 1);
                m = 0;
            }
                
            printf("Prime factorization: %"PRId64" = ", n);
            for (i = 0 ; i < 2*nfactor; i += 2)
            {
                printf("%"PRId64"^{%"PRId64"} ", factors[i], factors[i + 1]);
            }
            printf("\n");
            printf("The number of positive divisors:  tau(%"PRId64") =  %"PRId64".\n", n, ndivisor);
            printf("The sum of all positive divisors:  sigma(%"PRId64") = %"PRId64".\n", n, nsum);
            printf("The number of positive integers relatively prime:  phi(%"PRId64") = %"PRId64"\n", n, nphi);
            if (nsum == n + 1)
                printf("The integer %"PRId64" is a prime number.\n", n);
            else
                printf("The integer %"PRId64" is not a prime number.\n", n);

            divisors = (long long *)malloc(sizeof(long long)*ndivisor);

            cnt = 0;
            ndx = 0;
            divisors[ndx] = 1;
            ndx += 1;
            cnt = 1;
            for (i = 0; i < 2*nfactor; i += 2)
            {
                p = factors[i];
                m = factors[i + 1];
                for (k = 1; k <= m; k++)
                {
                    for (j = 0; j < cnt; j++)
                    {
                        divisors[ndx] = divisors[j]*pow(p, k);
                        ndx += 1;
                    }
                }
                cnt = ndx;
            }
            printf("The positive divisors of %"PRId64" are\n", n);
            for (i = 0; i < ndivisor - 1; i++)
            {
                printf("%"PRId64", ", divisors[i]);
            }
            printf("%"PRId64".\n", divisors[ndivisor - 1]);
        }
    }
 
    free(factors);
    free(divisors);
 
    return 0;
}

 

 

실행> eulerPhiGoodC_01 240
Prime factorization: 240 = 2^{4} 3^{1} 5^{1}
The number of positive divisors:  tau(240) =  20.
The sum of all positive divisors:  sigma(240) = 744.
The number of positive integers relatively prime:  phi(240) = 64
The integer 240 is not a prime number.
The positive divisors of 240 are
1, 2, 4, 8, 16, 3, 6, 12, 24, 48, 5, 10, 20, 40, 80, 15, 30, 60, 120, 240.

실행> eulerPhiGoodC_01 24345
Prime factorization: 24345 = 3^{2} 5^{1} 541^{1}
Prime factorization: 24345 = 3^{2} 5^{1} 541^{1}
The number of positive divisors:  tau(24345) =  12.
The sum of all positive divisors:  sigma(24345) = 42276.
The number of positive integers relatively prime:  phi(24345) = 12960
The integer 24345 is not a prime number.
The positive divisors of 24345 are
1, 3, 9, 5, 15, 45, 541, 1623, 4869, 2705, 8115, 24345.

실행> eulerPhiGoodC_01 2434500
Prime factorization: 2434500 = 2^{2} 3^{2} 5^{3} 541^{1}
The number of positive divisors:  tau(2434500) =  72.
The sum of all positive divisors:  sigma(2434500) = 7694232.
The number of positive integers relatively prime:  phi(2434500) = 648000
The integer 2434500 is not a prime number.
The positive divisors of 2434500 are
1, 2, 4, 3, 6, 12, 9, 18, 36, 5, 10, 20, 15, 30, 60, 45, 90, 180, 25, 50, 100, 7
5, 150, 300, 225, 450, 900, 125, 250, 500, 375, 750, 1500, 1125, 2250, 4500, 541
, 1082, 2164, 1623, 3246, 6492, 4869, 9738, 19476, 2705, 5410, 10820, 8115, 1623
0, 32460, 24345, 48690, 97380, 13525, 27050, 54100, 40575, 81150, 162300, 121725
, 243450, 486900, 67625, 135250, 270500, 202875, 405750, 811500, 608625, 1217250
, 2434500.

실행> eulerPhiGoodC_01 481000000008
Prime factorization: 481000000008 = 2^{3} 3^{1} 11^{1} 73^{1} 24958489^{1}
The number of positive divisors:  tau(481000000008) =  64.
The sum of all positive divisors:  sigma(481000000008) = 1329788347200.
The number of positive integers relatively prime:  phi(481000000008) = 143760890
880
The integer 481000000008 is not a prime number.
The positive divisors of 481000000008 are
1, 2, 4, 8, 3, 6, 12, 24, 11, 22, 44, 88, 33, 66, 132, 264, 73, 146, 292, 584, 2
19, 438, 876, 1752, 803, 1606, 3212, 6424, 2409, 4818, 9636, 19272, 24958489, 49
916978, 99833956, 199667912, 74875467, 149750934, 299501868, 599003736, 27454337
9, 549086758, 1098173516, 2196347032, 823630137, 1647260274, 3294520548, 6589041
096, 1821969697, 3643939394, 7287878788, 14575757576, 5465909091, 10931818182, 2
1863636364, 43727272728, 20041666667, 40083333334, 80166666668, 160333333336, 60
125000001, 120250000002, 240500000004, 481000000008.

실행> eulerPhiGoodC_01 481000000009
Prime factorization: 481000000009 = 83^{1} 347^{1} 3361^{1} 4969^{1}
The number of positive divisors:  tau(481000000009) =  16.
The sum of all positive divisors:  sigma(481000000009) = 488441580480.
The number of positive integers relatively prime:  phi(481000000009) = 473599042
560
The integer 481000000009 is not a prime number.
The positive divisors of 481000000009 are
1, 83, 347, 28801, 3361, 278963, 1166267, 96800161, 4969, 412427, 1724243, 14311
2169, 16700809, 1386167147, 5795180723, 481000000009.

실행> eulerPhiGoodC_01 481000000001
Prime factorization: 481000000001 = 367^{1} 1310626703^{1}
The number of positive divisors:  tau(481000000001) =  4.
The sum of all positive divisors:  sigma(481000000001) = 482310627072.
The number of positive integers relatively prime:  phi(481000000001) = 479689372
932
The integer 481000000001 is not a prime number.
The positive divisors of 481000000001 are
1, 367, 1310626703, 481000000001.

 

 

 

Posted by Scripter
,