다음 소스는 g++ 4.6.2, g++ 4.8.0, g++ 4.8.1 그리고 Visual Studio 2013 Express 의 cl 로 컴파일됨이 확인되었다.

(g++ 4.5.3 과 Visual Studio 2010 의 cl 로는 range based for 구문 때문에 컴파일되지 않는다.)

 

// Filename: vector_for_loop_01.cpp
//
//      Purpose:  How to use vector types and for loops.
//
// With g++ 4.6 above
// Compile: g++ -std=c++0x -o vector_for_loop_01 vector_for_loop_01.cpp
// Compile: g++ -std=c++11 -o vector_for_loop_01 vector_for_loop_01.cpp
// Execute: ./vector_for_loop_01
//
//   or
//
// With Visual C++ 12
// Compile: cl /EHsc vector_for_loop_01.cpp
// Execute: vector_for_loop_01
//
// See: http://stackoverflow.com/questions/409348/iteration-over-vector-in-c

#include <vector>
#include <iostream>

int main(void) {
    std::vector<int> v = std::vector<int>();
    v.push_back(17);
    v.push_back(12);
    v.push_back(23);
    v.push_back(42);
    for ( auto &i : v ) {
        std::cout << i << std::endl;
    }
    return 0;
}

/*
Output:
17
12
23
42
*/

 

참고로 위의 소스를 Visual C++ 10.0(즉 Visual Studio 2010 의 C++)의 명령줄 컴파일러 cl 로 컴파일하면 다음의 에러메세지가 나온다.

------------------------------------------------------------------------

Microsoft (R) 32비트 C/C++ 최적화 컴파일러 버전 16.00.40219.01(80x86)
Copyright (c) Microsoft Corporation. 모든 권리 보유.

vector_for_loop_01.cpp
vector_for_loop_01.cpp(27) : error C2143: 구문 오류 : ','이(가) ':' 앞에 없습니다.
vector_for_loop_01.cpp(27) : error C2530: 'i' : 참조를 초기화해야 합니다.
vector_for_loop_01.cpp(27) : error C3531: 'i': 형식에 'auto'가 포함된 기호에는이니셜라이저가 있어야 합니다.
vector_for_loop_01.cpp(27) : error C2143: 구문 오류 : ';'이(가) '{' 앞에 없습니다.

------------------------------------------------------------------------

 

또한 위의 소스를 cygwin 의 g++ 4.5.3 으로 컴파일하면 다음의 에러메세지가 나온다.

--------------------------------------------------------

vector_for_loop_01.cpp: In function ‘int main()’:
vector_for_loop_01.cpp:27:19: error: expected initializer before ‘:’ token
vector_for_loop_01.cpp:30:5: error: expected primary-expression before ‘return

vector_for_loop_01.cpp:30:5: error: expected ‘;’ before ‘return’
vector_for_loop_01.cpp:30:5: error: expected primary-expression before ‘return

vector_for_loop_01.cpp:30:5: error: expected ‘)’ before ‘return’
-----------------------------------------------------------------------

 

 

다음 소스는 g++ 4.5.3 및  Visual Studio 2010 의 cl 로도 컴파일되도록 for 반목문을 수정한 것이다.

 

// Filename: vector_for_loop_02.cpp
//
//      Purpose:  How to use vector types and for loops.
//
// With g++ 4.5 above
// Compile: g++ -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp
// Compile: g++ -std=c++11 -o vector_for_loop_02 vector_for_loop_02.cpp
// Execute: ./vector_for_loop_02
//
//   or
//
// With Visual C++ 10
// Compile: cl /EHsc vector_for_loop_02.cpp
// Execute: vector_for_loop_02
//
// See: http://stackoverflow.com/questions/409348/iteration-over-vector-in-c

#include <vector>
#include <iostream>

int main(void) {
    std::vector<int> v = std::vector<int>();
    v.push_back(17);
    v.push_back(12);
    v.push_back(23);
    v.push_back(42);
    // for ( auto &i : v ) {
    //     std::cout << i << std::endl;
    // }
    for ( auto it = v.begin(); it != v.end(); it++ ) {
        std::cout << *it << std::endl;
    }
    return 0;
}

/*
Output:
17
12
23
42
*/

 

[참고] --enable-auto-import 에러가 날 때

위의 소스가 HaskellPlatforem 에 설치된 mingw 의 (버전 4.5.2 인) g++ 로 캄파일할 때 --enable-auto-import 에러가 날 때가 있다.

C:\test\mingw>g++ -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp
Info: resolving std::cout  by linking to __imp___ZSt4cout (auto-import)
d:/haskellplatform/mingw/bin/../lib/gcc/mingw32/4.5.2/../../../../mingw32/bin/ld
.exe: warning: auto-importing has been activated without --enable-auto-import sp
ecified on the command line.
This should work unless it involves constant data structures referencing symbols
 from auto-imported DLLs.

 

원인은 디헥토리 D:\HaskellPlatform\mingw\lib\gcc\mingw32\4.5.2  에 있는 라이브러리 파일 libstdc++.dll.a 을 찾지 못해 일어나는 에러인 것 같은데 이를 어떻게 해결해냐 하는가?

 

g++ 로 컴파할 때 옵션 --enable-auto-import 를 주고 해보았다.

C:\test\mingw>g++ --enable-auto-import -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp
cc1plus.exe: error: unrecognized command line option "-fenable-auto-import"

옵션이 인식이 안된다, 이러 때는 옵션

               -enable-auto-import   또는  -Wl,--enable-auto-import

르 주면 에러나 경고 없이 컴파일이 잘 된다.

C:\test\mingw>g++ -enable-auto-import -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp

C:\test\mingw>g++ -Wl,--enable-auto-import -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp

C:\test\mingw>vector_for_loop_02
17
12
23
42

 

이제 좀 더 편안한 방법을 찾아 보자.

윈도우즈 명령창에서 doskey 를 이용하여 명령 g++ -enable-auto-import 대신할 명령 s++ 를 생성한다.

C:\test\mingw>doskey s++=g++ -enable-auto-import $*

 

이제 s++ 명령으로 컴파일도 하고 실행도 해본다.

C:\test\mingw>s++ -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp

C:\test\mingw>vector_for_loop_02
17
12
23
42

 

명렬창을 열때 미리 저런 doskey 설정을 해도 된다.  윈도우카+R 을 눌러서

 

처럼 입력하고 "획인 버튼을 누른다.  이제 새로 열린 명령창에서 컴파일하여 실행한다,

 

 

명령창을 열 때마다 저런 길다란 옵션을 외워서 쓰기도 번거롭다. 그래서 더 편안한 방법으로 "바로가기 명령창 아이콘"을 바탕화면에 링크시켜 놓는다.

 

이제 바탕화면에 깔린 저 아이콘에 마우스 우측 버튼을 클릭하여 속성을 설정한다. 성정할 부분은 아래의 두 그림 처럼 "대상(T)"과 "시작 위치(S)"이다. ("대상(T)" 부분에 입력할 글자가 길어서 그림을 두 개로 만들었다.)

 

 

 

 

이제 저 바탕화면을 클릭하면 g++ 명령 대신 s++ 명령으로 컴파일할 수 있다.

 

* 참고 자료: http://stackoverflow.com/questions/7742332/purpose-of-enable-auto-import-warning

 

 

Posted by Scripter
,

아래의 소스는 (64 비트) 윈도우 8 에서 Visual Studio 2013 Express 의 명령줄 컴파일러 cl 및 cygwin64 의 컴파일러 g++ 로 테스트되었다. (소스를 저장할 시, Visual C++ 용으로는 KSC5601-1987 인코딩으로 저장하고, cygwin64 의 g++ 용으로는 UTF-8 인코딩으로 저장해야 한글이 정상 출력된다.)

 

vector 타입을 초기화(initializer lists)하는 구문

    vecor<T> v { .... }

또는

   vector<T> v = { ... }

은 C++0x(정확하게는 C++09 이후) 또는 C++11 에서만 지원되는 구문이다.

그러므로 다음 소스는 Visual Studio 2010 이나 g++ 의 버전이 4.4 미만이면 컴파일되지 않는다. Visual Studio 2012 도 최소한 November 2012 CTP 이후라야 컴퍼일된다.
 

        [참고 1] Vector initialization with more values in c++11

        [참고 2] Initializer list not working with vector in Visual Studio 2012?

        [참고 3] C++0x Core Language Features In VC10: The Table

        [참고 4] C++11 Features in Visual C++ 11

        [참고 5] C++0x initialization: Lists

 

// Filename: initializeVector_02.cpp
//
// Compile: cl /EHsc initializeVector_02.cpp
// Execute: initializeVector_02
//
//      or
//
// Compile: g++ -std=c++11  -o initializeVector_02 initializeVector_02.cpp
// Execute: ./initializeVector_02
//
// Date: 2013. 9. 25.

#include <iostream>
#include <vector>
#include <cmath>

template <typename T>
void printVector(std::vector<T> v)
{
    std::cout << "[";
    for (auto it = std::begin(v); it != std::end(v); it++)
    {
        std::cout << *it;
        if ((it + 1) != std::end(v))
            std::cout << ", ";
    }
    std::cout << "]";
    std::cout << std::endl;
}

int main()
{
    std::cout << "Hello, 안녕하세요?" << std::endl;

    std::vector<double> v1 = { 1, 2, 3, 4, 5 };
    std::cout << "v1 = ";
    printVector(v1);

    std::cout << "v2 = ";
    std::vector<double> v2 = { sin(v1[0]), cos(v1[1]), exp(v1[2]), log(v1[3]), pow(2, v1[4]) };
    printVector(v2);

    return 0;
}

/*
Output:
Hello, 안녕하세요?
v1 = [1, 2, 3, 4, 5]
v2 = [0.841471, -0.416147, 20.0855, 1.38629, 32]
*/

 

* Visual Studio 2012 Express for Windows 8 의 컴파일러 cl 을 사용하여 위의 소스를 컴파일한 경우의 컴파일 에러 메세지

Prompt> cl /EHsc initializeVector_02.cpp
x86용 Microsoft (R) C/C++ 최적화 컴파일러 버전 17.00.50727.1
Copyright (c) Microsoft Corporation. All rights reserved.

initializeVector_02.cpp
initializeVector_02.cpp(34) : error C2552: 'v1' : 이니셜라이저 목록을 사용하여
비집합체를 초기화할 수 없습니다.
        'std::vector<_Ty>' : 기본이 있는 형식은 집합체가 아닙니다.
        with
        [
            _Ty=double
        ]
initializeVector_02.cpp(39) : error C2552: 'v2' : 이니셜라이저 목록을 사용하여
비집합체를 초기화할 수 없습니다.
        'std::vector<_Ty>' : 기본이 있는 형식은 집합체가 아닙니다.
        with
        [
            _Ty=double
        ]

 

* cygwin64 의 (버전 4.8.1 인) 컴파일러 g++ 로 옵션 -std=c++0x 또는 -std=c++11 을 주어 위의 소스를 성공적으로 컴파일하고 실행한 경우

g++ -std=c++0x  -o initializeVector_02 initializeVector_02.cpp

$ ./initializeVector_02
Hello, 안녕하세요?
v1 = [1, 2, 3, 4, 5]
v2 = [0.841471, -0.416147, 20.0855, 1.38629, 32]

g++ -std=c++11  -o initializeVector_02 initializeVector_02.cpp

$ ./initializeVector_02
Hello, 안녕하세요?
v1 = [1, 2, 3, 4, 5]
v2 = [0.841471, -0.416147, 20.0855, 1.38629, 32]

 

Posted by Scripter
,

다음 소스는 GNU CLisp 으로 실행됨을 확인하였다.

세 함수 pyra1(int int), pyra2(int int), pyra3(int int) 는 재귀호출을 사용하였고, 세 함수 pyramid1(), pyramid2(), pyramid3() 은 loop for 반복문을 사용하였다.

 

#!/usr/bin/env clisp

;;  Filename: pyramidOfDigits2.lsp
;;
;;   Execute: clisp pyramidOfDigits2.lsp
;;
;;     Or
;;
;;   Execute: ./pyramidOfDigits2.lsp
;;
;;     See: http://darvish.wordpress.com/2008/03/16/the-beauty-of-mathematics-and-the-love-of-god/
;;
;;  Date: 2013. 9. 23.
;;  Copyright (c) 2013 PH Kim  (pkim __AT__ scripts.pe.kr)


(setf *TEN*   10)
(setf *NINE*   9)
(setf *EIGHT*  8)


(defun pyra1(n i)
    (if (<= i *NINE*) (progn
 (format t "~9D x ~A + ~A = ~A~%" n *EIGHT* i (+ (* n *EIGHT*) i))
        (if (< i *NINE*)
      (pyra1 (+ (* n *TEN*) (+ i 1)) (+ i 1))))))

(defun pyra2(n i)
    (if (>= i 0) (progn
        (format t "~8D x ~A + ~A = ~A~%" n *NINE* i (+ (* n *NINE*) i))
        (if (> i 0)
      (pyra2 (+ (* n *TEN*) (+ i 1)) (- i 1))))))

(defun pyra3(n i)
    (if (<= i *TEN*) (progn
 (format t "~9D x ~A + ~2D = ~A~%" n *NINE* i (+ (* n *NINE*) i))
        (if (< i *TEN*)
      (pyra3 (+ (* n *TEN*) i) (+ i 1))))))

(defun pyramid1()
     (let ((i 0)
           (n 0)
           (s (make-list *TEN* :initial-element #\Space)))
 (loop for i from 1 below *TEN* do
  (setf (nth (- i 1) s) (code-char (+ 48 i)))
  (setf (nth i s)  #\Space)
  (setf n (parse-integer (list-to-string s)))
  (format t "~9D x ~A + ~A = ~A~%" n *EIGHT* i (+ (* n *EIGHT*) i)))
    ))

(defun pyramid2()
     (let ((i 0)
           (n 0)
           (s (make-list *TEN* :initial-element #\Space)))
 (loop for i from *NINE* downto 2 do
                ; (format t " i = ~A~%" i)
  (setf (nth (- *NINE* i) s) (code-char (+ 48 i)))
  (setf (nth (+ (- *NINE* i) 1) s) #\Space)
  (setf n (parse-integer (list-to-string s)))
  (format t "~8D x ~A + ~2A = ~A~%" n *NINE* (- i 2) (+ (* n *NINE*) (- i 2))))
    ))

(defun list-to-string (a)
    (format nil "~{~A~^~}" a))


(defun pyramid3()
     (let ((i 0)
           (n 0)
           (s (make-list *TEN* :initial-element #\Space)))
 (loop for i from 1 below *TEN* do
  (setf (nth (- i 1) s) (code-char (+ 48 i)))
  (setf (nth i s)  #\Space)
  (setf n (parse-integer (list-to-string s)))
  (format t "~9D x ~A + ~2D = ~A~%" n *NINE* (+ i 1) (+ (* n *NINE*) (+ i 1))))))


(format t "Use for loops~%")
(format t "Pyramid 1~%")
(pyramid1)
(format t "~%")

(format t "Pyramid 2~%")
(pyramid2)
(format t "~%")

(format t "Pyramid 3~%")
(pyramid3)
(format t "~%")

(format t "Use recursively called functions~%")
(format t "Pyramid 1~%")
(pyra1 1 1)
(format t "~%")

(format t "Pyramid 2~%")
(pyra2 9 7)
(format t "~%")

(format t "Pyramid 3~%")
(pyra3  1 2)
(format t "~%")


#|
Output:
Use for loops
Pyramid 1
        1 x 8 + 1 = 9
       12 x 8 + 2 = 98
      123 x 8 + 3 = 987
     1234 x 8 + 4 = 9876
    12345 x 8 + 5 = 98765
   123456 x 8 + 6 = 987654
  1234567 x 8 + 7 = 9876543
 12345678 x 8 + 8 = 98765432
123456789 x 8 + 9 = 987654321

Pyramid 2
       9 x 9 + 7  = 88
      98 x 9 + 6  = 888
     987 x 9 + 5  = 8888
    9876 x 9 + 4  = 88888
   98765 x 9 + 3  = 888888
  987654 x 9 + 2  = 8888888
 9876543 x 9 + 1  = 88888888
98765432 x 9 + 0  = 888888888

Pyramid 3
        1 x 9 +  2 = 11
       12 x 9 +  3 = 111
      123 x 9 +  4 = 1111
     1234 x 9 +  5 = 11111
    12345 x 9 +  6 = 111111
   123456 x 9 +  7 = 1111111
  1234567 x 9 +  8 = 11111111
 12345678 x 9 +  9 = 111111111
123456789 x 9 + 10 = 1111111111

Use recursively called functions
Pyramid 1
        1 x 8 + 1 = 9
       12 x 8 + 2 = 98
      123 x 8 + 3 = 987
     1234 x 8 + 4 = 9876
    12345 x 8 + 5 = 98765
   123456 x 8 + 6 = 987654
  1234567 x 8 + 7 = 9876543
 12345678 x 8 + 8 = 98765432
123456789 x 8 + 9 = 987654321

Pyramid 2
       9 x 9 + 7 = 88
      98 x 9 + 6 = 888
     987 x 9 + 5 = 8888
    9876 x 9 + 4 = 88888
   98765 x 9 + 3 = 888888
  987654 x 9 + 2 = 8888888
 9876543 x 9 + 1 = 88888888
98765432 x 9 + 0 = 888888888

Pyramid 3
        1 x 9 +  2 = 11
       12 x 9 +  3 = 111
      123 x 9 +  4 = 1111
     1234 x 9 +  5 = 11111
    12345 x 9 +  6 = 111111
   123456 x 9 +  7 = 1111111
  1234567 x 9 +  8 = 11111111
 12345678 x 9 +  9 = 111111111
123456789 x 9 + 10 = 1111111111
|#

 

 

Posted by Scripter
,

다음은 행렬 곱셈을 수행하는 C++ 언어 소스이다.

행의 수, 열의 수. 그리고 두 행렬의 요소들을 모두 컨솔에서 입력해야 한다.

소스는 http://www.physics.utah.edu/~detar/lessons/c++/matrices/node4.html 의 것을 다소 수정한 것이다.

 

// Filename: testSomeMat-03.cpp
//
// Copmpile: cl /EHsc testSomeMat-03.cpp
// Execute: testSomeMat-03
//
// Date: 2003.9. 20.

#include <iostream>
#include <vector>
#include <iomanip>
 
using namespace std;

typedef vector<double> Vec;
typedef vector<Vec> Mat;

Vec operator*(const Mat &a, const Vec &x){
  int i,j;
  int m = a.size();
  int n = x.size();

  Vec prod(m);

  for(i = 0; i < m; i++){
    prod[i] = 0.;
    for(j = 0; j < n; j++)
      prod[i] += a[i][j]*x[j];
  }
  return prod;
}

Mat operator*(const Mat &a, const Mat &b) {
  int i, j, k;
  int m = a.size();
  int n = a[0].size();
  int p = b[0].size();

  Mat c;

  for(i = 0; i < m; i++){
    Vec row(p);
    for(j = 0; j < p; j++) {
      row[j] = 0.;
      for(k = 0; k < n; k++) {
          row[j] += a[i][k]*b[k][j];
      }
    }
    c.push_back(row);
  }
  return c;
}

void printMatrix(const Mat &a, int width) {
  int i, j;
  int m = a.size();
  int n = a[0].size();

  for(i = 0; i < m; i++) {
     if (i == 0)
        cout << "  [[";
     else
        cout << "   [";
      for(j = 0; j < n; j++) {
        cout << "  " << setw(width) << a[i][j];
      }
     if (i < m - 1)
          cout << "  ]";
     else
          cout << "  ]]";
      cout << "\n";
  }
}

int main() {

  int i, j, k, m, n, p;

  cout << "첫째 행렬의 행의 수: ";
  cin >> m;
  cout << "첫째 행렬의 열의 수: ";
  cin >> n;
  cout << "둘째 행렬의 열의 수: ";
  cin >> p;

  cout << "\n";
  
  // 첫째 행렬과 이 행렬의 입력을 위한 벡터 선언
  Mat a;
  Vec row(n);

  cout << "첫째 행렬의 요소들을 입력하시오.\n";
  for(i = 0; i < m; i++){
    for(j = 0; j < n; j++)cin >> row[j];
    a.push_back(row);
  }

  // 둘째 행렬과 이 행렬의 입력을 위한 벡터 선언
  Mat b;
  Vec row2(p);

  cout << "둘째 행렬의 요소들을 입력하시오.\n";
  for(i = 0; i < n; i++){
    for(j = 0; j < p; j++)cin >> row2[j];
    b.push_back(row2);
  }


  Mat c = a*b;

  cout << "\nA = \n";
  printMatrix(a, 8);

  cout << "\nB = \n";
  printMatrix(b, 8);

  cout << "\nA*B = \n";
  printMatrix(c, 8);

  return 0;
}

/*
Output:
첫째 행렬의 행의 수: 3
첫째 행렬의 열의 수: 3
둘째 행렬의 열의 수: 1

첫째 행렬의 요소들을 입력하시오.
 2  5 6
1 2 0
9 7 1
둘째 행렬의 요소들을 입력하시오.
4 1 2

A =
  [[         2         5         6  ]
   [         1         2         0  ]
   [         9         7         1  ]]

B =
  [[         4  ]
   [         1  ]
   [         2  ]]

A*B =
  [[        25  ]
   [         6  ]
   [        45  ]]
*/

 

 

다음은 정사각행렬의 행렬식을 구하는 소스이다.

// Filename: determinant-04.cpp
//
// Compile: g++ -std=c++11 -o determinant-04 determinant-04.cpp
// Execute: ./determinant-04
//
//     or
//
// Compile: cl /EHsc determinant-04.cpp
// Execute: determinant-04
//
// Date: 2013. 9. 20.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <cstring>

using namespace std;

typedef vector<double> Vec;
typedef vector<Vec> Mat;

Vec operator*(const Mat &a, const Vec &x){
  int i,j;
  int m = a.size();
  int n = x.size();

  Vec prod(m);

  for(i = 0; i < m; i++){
    prod[i] = 0.;
    for(j = 0; j < n; j++)
      prod[i] += a[i][j]*x[j];
  }
  return prod;
}

Mat operator*(const Mat &a, const Mat &b) {
  int i, j, k;
  int m = a.size();
  int n = a[0].size();
  int p = b[0].size();

  Mat c;

  for(i = 0; i < m; i++){
    Vec row(p);
    for(j = 0; j < p; j++) {
      row[j] = 0.;
      for(k = 0; k < n; k++) {
          row[j] += a[i][k]*b[k][j];
      }
    }
    c.push_back(row);
  }
  return c;
}

void printMatrix(const Mat &a, int width) {
  int i, j;
  int m = a.size();
  int n = a[0].size();

  for(i = 0; i < m; i++) {
     if (i == 0)
        cout << "  [[";
     else
        cout << "   [";
      for(j = 0; j < n; j++) {
        cout << "  " << setw(width) << a[i][j];
      }
     if (i < m - 1)
          cout << "  ]";
     else
          cout << "  ]]";
      cout << "\n";
  }
}

void printPermutation(const vector<int> pmt, int counter)
{
    int n = pmt.size();
    cout << "[";
    if (n > 0)
    {
        cout << " " << pmt[0];
        if (n > 1)
        {
            for (int i = 1; i < n; i++)
            {
                cout << ", " << pmt[i];
            }
        }
        cout << " ";
    }
    cout << "]";
    if ((counter % 2) == 0)
        cout << "    -- even --";
    else
        cout << "    -- odd  --";
    cout << endl;
}

void swap(vector<int> &pmt, int i, int j)
{
    int x = pmt[j];
    pmt[j] = pmt[i];
    pmt[i] = x;
}


 

void doPermute(const Mat &mat, int dim, vector<int> pmt, int size, int &cnt, double &det, bool show_flag)
{
    double x;
    double y;
    if (size == 2)
    {
       if (show_flag)
            printPermutation(pmt, cnt);
        x = 1.0;
        for (int j = 0; j < dim; j++)
        {
         if (mat[j][pmt[j]] == 0) {
          x = 0;
          break;
         }
         x *= mat[j][pmt[j]];
        }
        det += ((cnt % 2) == 0) ? x : -x;
        swap(pmt, 0, 1);
        cnt++;
        if (show_flag)
            printPermutation(pmt, cnt);
        x = 1.0;
        for (int j = 0; j < dim; j++)
        {
           if (mat[j][pmt[j]] == 0) {
          x = 0.0;
          break;
         }
        x *= mat[j][pmt[j]];
        }
        det += ((cnt % 2) == 0) ? x : -x;
        swap(pmt, 0, 1);
        cnt--;
    }
    else if (size > 2)
    {
        doPermute(mat, dim, pmt, size - 1, cnt, det, show_flag);
        for (int i = size - 2; i >= 0; i--)
        {
             swap(pmt, i, size - 1);
             cnt++;
             doPermute(mat, dim, pmt, size - 1, cnt, det, show_flag);
        }
        for (int i = 0; i <= size - 2; i++)
        {
            swap(pmt, i, size - 1);
            cnt--;
        }
    }
}

int main(int argc, const char *argv[])
{
    // vector<int> v = { 0, 1, 2, 3, 4 };     // syntax for C++11
    vector<int> v(5);
    for (int i = 0; i < 5; i++)
    {
     v[i] = i;
    }
   
    int counter = 0;
    int dim = 3;
    int n = 3;
    double d = 0.0;
    
    cout << "정사각행렬의 행의 수: ";
    cin >> n;

     // Allocate space for the vectors
     Mat a;
     Vec row(n);

     cout << "행렬의 모든 요소를 입력하시오.\n";
     for (int i = 0; i < n; i++) {
         for (int j = 0; j < n; j++) {
             cin >> row[j];
         }
         a.push_back(row);
     }

     cout << "\nA = \n";
     printMatrix(a, 8);


    if (n > 5)
    {
        for (int i = 5; i < n; i++)
        {
            v.push_back(i);
        }
    }
    else if (n < 5) {
       for (int i = 0; i < 5 - n; i++)
       {
          v.pop_back();
       }
    }

    dim = n;


    cout << endl;
    
    bool show_flag = false;    // true;    // false;
    doPermute(a, dim, v, n, counter, d, show_flag);

    if (show_flag)
        cout << endl;
    cout << "A의 행렬식: det(A) = " << d << endl;
    return 0;
}

/*
Execute & Output:
정사각행렬의 행의 수: 2
행렬의 모든 요소를 입력하시오.
7 8
9 2

A =
  [[         7         8  ]
   [         9         2  ]]

A의 행렬식: det(A) = -58
*/

 

 

Posted by Scripter
,

정리 (정사각행렬의 행렬식, derterminant)

n × n 행렬 A = \big( a_{ij} \big) 의 행렬식 \det(A) 는 다음 식과 같다

         \det(A) \ = \ \sum_{\sigma} \, \textrm{sign}(\sigma) \, a_{1 \sigma(1)} a_{2 \sigma(2)} \cdots a_{n \sigma(n)}

위에서 합은 집합 \{ 1, 2, \cdots, n \} 위에서의 모든 순열 \sigma에 관한 합이며, \textrm{sign}(\sigma)\sigma가 우순열인 경우에는 +1이고, 기순열인 경우에는 -1이다.

 

다음의 C++ 언어로 작성된 소스는 순열을 출력하는 소스를 수정아여 정사각행렬의 행렬식을 계산하도록 하였다.

컴파일은 g++ 또는 Visual C++ 의 명령줄 컴파일러 cl 을 이용한다.

 

// Filename: determinant-03.cpp
//
// Compile: g++ -std=c++11 -o determinant-03 determinant-03.cpp
// Execute: ./determinant-03 [integer]
//
//     or
//
// Compile: cl /EHsc determinant-03.cpp
// Execute: determinant-03 [integer]
//
// Date: 2013. 9. 20.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <cstring>

using namespace std;

template<typename T>
class Array2D
{
    private:
        const int width;
        T * data;
    public:
        T& operator() (int x, int y) { return data[y*width + x]; }
        Array2D(const int w, const int h) : width(w) { data = new T[w*h]; }
        ~Array2D() { delete [] data; }
};

void printPermutation(const vector<int> pmt, int counter)
{
    int n = pmt.size();
    cout << "[";
    if (n > 0)
    {
        cout << " " << pmt[0];
        if (n > 1)
        {
            for (int i = 1; i < n; i++)
            {
                cout << ", " << pmt[i];
            }
        }
        cout << " ";
    }
    cout << "]";
    if ((counter % 2) == 0)
        cout << "    -- even --";
    else
        cout << "    -- odd  --";
    cout << endl;
}

void swap(vector<int> &pmt, int i, int j)
{
    int x = pmt[j];
    pmt[j] = pmt[i];
    pmt[i] = x;
}

void printMatrix(Array2D<double> &mat, int nrow, int ncol)
{
    for (int i = 0; i < nrow; i++)
    {
        cout << "[[";
        for (int j = 0; j < ncol; j++)
        {
            cout << " " << setw(9) << mat(i, j) << " ";
        }
        cout << "  ]]" << endl;
    }
    cout << endl;
}

#include <sstream>
void readMatrix(Array2D<double> &mat, int nrow, int ncol)
{
  std::string line;
     double x;
     int i = 0;
     while (i < nrow*ncol)
     {
          cin >> line;
          std::istringstream iss(line);
          while (iss)
          {
              std::string sub;
              iss >> sub;

              std::istringstream ins(sub);
              if (!(ins >> x))
                  break;
              mat(i / ncol, i % ncol) = x;
              i++;
          }
     }
}

void doPermute(Array2D<double> &mat, int dim, vector<int> pmt, int size, int &cnt, double &det, bool show_flag)
{
    double x;
    double y;
    if (size == 2)
    {
       if (show_flag)
            printPermutation(pmt, cnt);
        x = 1.0;
        for (int j = 0; j < dim; j++)
        {
         if (mat(j, pmt[j]) == 0) {
          x = 0;
          break;
         }
         x *= mat(j, pmt[j]);
        }
        det += ((cnt % 2) == 0) ? x : -x;
        swap(pmt, 0, 1);
        cnt++;
        if (show_flag)
            printPermutation(pmt, cnt);
        x = 1.0;
        for (int j = 0; j < dim; j++)
        {
           if (mat(j, pmt[j]) == 0) {
          x = 0.0;
          break;
         }
        x *= mat(j, pmt[j]);
        }
        det += ((cnt % 2) == 0) ? x : -x;
        swap(pmt, 0, 1);
        cnt--;
    }
    else if (size > 2)
    {
        doPermute(mat, dim, pmt, size - 1, cnt, det, show_flag);
        for (int i = size - 2; i >= 0; i--)
        {
             swap(pmt, i, size - 1);
             cnt++;
             doPermute(mat, dim, pmt, size - 1, cnt, det, show_flag);
        }
        for (int i = 0; i <= size - 2; i++)
        {
            swap(pmt, i, size - 1);
            cnt--;
        }
    }
}

int main(int argc, const char *argv[])
{
    // vector<int> v = { 0, 1, 2, 3, 4 };     // syntax for C++11
    vector<int> v(5);
    for (int i = 0; i < 5; i++)
    {
     v[i] = i;
    }
   
    int counter = 0;
    int dim = 3;
    int k = 3;
    double d = 0.0;


    if (argc > 1)
    {
        sscanf(argv[1], "%d", &k);
    }

    if (k > 5)
    {
        for (int i = 5; i < k; i++)
        {
            v.push_back(i);
        }
    }
    else if (k < 5) {
       for (int i = 0; i < 5 - k; i++)
       {
          v.pop_back();
       }
    }

    dim = k;
    Array2D<double> mat(dim, dim);

    cout << "Input a " << k << " by " << k << " matrix" << endl;

    readMatrix(mat, k, k);

    cout << endl;
    cout << "The given matrix is " << endl;
    printMatrix(mat, dim, dim);
   
    bool show_flag = false;
    doPermute(mat, dim, v, k, counter, d, show_flag);

    if (show_flag)
        cout << endl;
    cout << "Its determinant is " << d << "." << endl;
    return 0;
}

/*
Execute & Output:
명령프롬프트> determinant-03
Input a 3 by 3 matrix
1 2 3   4 5 6.02   7 8.1   9

The given matrix is
[[         1          2          3   ]]
[[         4          5       6.02   ]]
[[         7        8.1          9   ]]

Its determinant is 0.718.

명령프롬프트> determinant-03 2
Input a 2 by 2 matrix
7 8
0.1 5.1

The given matrix is
[[         7          8   ]]
[[       0.1        5.1   ]]

Its determinant is 34.9.

명령프롬프트> determinant-03 4
Input a 4 by 4 matrix
1 2 3   4 5 6.02   7 8.1   9
0 0 0 7 0 2 3

The given matrix is
[[         1          2          3          4   ]]
[[         5       6.02          7        8.1   ]]
[[         9          0          0          0   ]]
[[         7          0          2          3   ]]

Its determinant is 32.22.
*/

 

 

 

Posted by Scripter
,

정의  (순열(또는 치환), permutation)

S가 집합일 때, S에서 S 위로 가는 일대일함수 즉, S에서 S로 가는 전단사함수를 집합 S 위에서의 순열이라고 한다, 특히 S가 원소 n개를 갖는 유한집합인 경우 S 위에서의 서로 다른 순열은 총 n!(n 팩토리얼)개이다.

 

다음의 C++ 언어로 작성된 소스는 유한집합 S = { 0, 1, 2, ... , n - 1 } 상에서의 모든 순열을 컨솔에 출력해준다. 우순열(even permutation)인지 기순열(odd permutation)인지도 판별해준다.

컴파일은 g++ 또는 Visual C++ 의 명령줄 컴파일러 cl 을 이용한다.

 

// Filename: permutations.cpp
//
// Compile: g++ -std=c++11 -o permutations permutations.cpp
// Execute: ./permutations [integer]
//
//     or
//
// Compile: cl /EHsc permutations.cpp
// Execute: permutations [integer]
//
// Date: 2013. 9. 20.

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void printVector(const vector<int> v, int counter)
{
    int n = v.size();
    cout << "[";
    if (n > 0)
    {
        cout << " " << v[0];
        if (n > 1)
        {
            for (int i = 1; i < n; i++)
            {
                cout << ", " << v[i];
            }
        }
        cout << " ";
    }
    cout << "]";
    if ((counter % 2) == 0)
        cout << "    -- even --";
    else
        cout << "    -- odd  --";
    cout << endl;
}

void swap(vector<int> &v, int i, int j)
{
    int x = v[j];
    v[j] = v[i];
    v[i] = x;
}

void doPermute(vector<int> v, int size, int &cnt)
{
    if (size == 2)
    {
        printVector(v, cnt);
        swap(v, 0, 1);
        cnt++;
        printVector(v, cnt);
        swap(v, 0, 1);
        cnt--;
    }
    else if (size > 2)
    {
        doPermute(v, size - 1, cnt);
        for (int i = size - 2; i >= 0; i--)
        {
            swap(v, i, size - 1);
            cnt++;
            doPermute(v, size - 1, cnt);
        }
        for (int i = 0; i <= size - 2; i++)
        {
            swap(v, i, size - 1);
            cnt--;
        }
    }
}

int main(int argc, const char *argv[])
{
    // vector<int> v = { 0, 1, 2, 3, 4 };     // syntax  for c++11
    vector<int> v(5);
    for (int i = 0; i < 5; i++)
    {
        v[i] = i;
    }

    int counter = 0;
    int k = 3;

    if (argc > 1)
    {
        sscanf(argv[1], "%d", &k);
    }

    if (k > 5)
    {
        for (int i = 6; i <= k; i++)
        {
            v.push_back(i);
        }
    }
    else if (k < 5) {
       for (int i = 0; i < 5 - k; i++)
       {
          v.pop_back();
       }
    }

    doPermute(v, k, counter);

    return 0;
}

/*
Execute & Output:

$ ./permutations
[ 0, 1, 2 ]    -- even --
[ 1, 0, 2 ]    -- odd  --
[ 0, 2, 1 ]    -- odd  --
[ 2, 0, 1 ]    -- even --
[ 1, 2, 0 ]    -- even --
[ 2, 1, 0 ]    -- odd  --


$ ./permutations 2
[ 0, 1 ]    -- even --
[ 1, 0 ]    -- odd  --


$ ./permutations 4
[ 0, 1, 2, 3 ]    -- even --
[ 1, 0, 2, 3 ]    -- odd  --
[ 0, 2, 1, 3 ]    -- odd  --
[ 2, 0, 1, 3 ]    -- even --
[ 1, 2, 0, 3 ]    -- even --
[ 2, 1, 0, 3 ]    -- odd  --
[ 0, 1, 3, 2 ]    -- odd  --
[ 1, 0, 3, 2 ]    -- even --
[ 0, 3, 1, 2 ]    -- even --
[ 3, 0, 1, 2 ]    -- odd  --
[ 1, 3, 0, 2 ]    -- odd  --
[ 3, 1, 0, 2 ]    -- even --
[ 0, 2, 3, 1 ]    -- even --
[ 2, 0, 3, 1 ]    -- odd  --
[ 0, 3, 2, 1 ]    -- odd  --
[ 3, 0, 2, 1 ]    -- even --
[ 2, 3, 0, 1 ]    -- even --
[ 3, 2, 0, 1 ]    -- odd  --
[ 1, 2, 3, 0 ]    -- odd  --
[ 2, 1, 3, 0 ]    -- even --
[ 1, 3, 2, 0 ]    -- even --
[ 3, 1, 2, 0 ]    -- odd  --
[ 2, 3, 1, 0 ]    -- odd  --
[ 3, 2, 1, 0 ]    -- even --
*/

 

 

Posted by Scripter
,

 

       (실수) = (정수부) + (소수부)      (단, 0 <= 소수부 < 1)

           x  = floor(x) + err           (단, 0<= err < 1)

           예:   3.14159  =  3 + 0.14150

                  -2.71828 = -3 + 0.26172

즉, floor(x) 는 x 보다 크지 않은 죄대의 정수를 의미한다. 수학에서 (기호 [x] 로 표기되는) 가우스 기호라고 부르는 함수에 해당한다.

 

C, C++, Java, Python, Ruby, C# 등의 대부분 언어에서는 floor 함수가 부동소수점수의 소소부를 잘라낸 정수부를 구하는데 쓰인다.

Common Lisp 언어에서는 floor 함수가 그런 용도로도 쓰이지만, Python 언어의 divmod 함수 처럼 몫과 나머지를 함께 구하는데 쓰이기도 한다.

 

우선 C 언어와 C++ 언어로 floor 함수를 사용하는 소스이다.

 

[ C 소스 파일명: testFloor.c ]

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

int main()
{
    printf("floor(-20.0/7) = %f\n", floor(-20.0/7));
    return 0;
}

/*
Output:
floor(-20.0/7) = -3.000000
*/

 

[ C++ 소스 파일명: testFloor.cpp ]

#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

int main()
{
    cout << "floor(-20.0/7) = ";
    cout << setprecision(6) << fixed;
    cout << floor(-20.0/7) << endl;
    return 0;
}

/*
Output:
floor(-20.0/7) = -3.000000
*/

 

 

그어면 Python 의 경우 divmod 함수의 사용 예를 알아 보자.

명령 프롬프트> python
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> divmod(23, 7)
(3, 2)
>>> (q, r) = divmod(23, 7)
>>> q
3
>>> r
2
>>> divmod(-20, 7)
(-3, 1)
>>>>>> quit()

 

 

이제 CLisp 의 경우에 대해서 알아 보자.

Common Lisp 언어의 floor 함수는 몫과 나머지를 함께 리턴하지만 리턴된 값들을 받으려면 다소 까다롭다. setq 나 setf 로는 안 되고 multiple-value-setq 를 사용해야 한다.

명령 프롬프트> clisp
  i i i i i i i       ooooo    o        ooooooo   ooooo   ooooo
  I I I I I I I      8     8   8           8     8     o  8    8
  I  \ `+' /  I      8         8           8     8        8    8
   \  `-+-'  /       8         8           8      ooooo   8oooo
    `-__|__-'        8         8           8           8  8
        |            8     o   8           8     o     8  8
  ------+------       ooooo    8oooooo  ooo8ooo   ooooo   8

Welcome to GNU CLISP 2.49 (2010-07-07) <http://clisp.cons.org/>

Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2010

Type :h and hit Enter for context help.

[1]> (floor 23 7)
3 ;
2
[2]> (multiple-value-setq (q r) (floor 23 7))
3
[3]> q
3
[4]> r
2
[5]> (floor -20 7)
-3 ;
1
[6]> (quit)
Bye.


 

 

multiple-value-setq 를 사용하는 더 간단한 예를 알아보자.

[1]> (multiple-value-setq (x y) (values 1 2))
1
[2]> (list x y)
(1 2)
[3]> (multiple-value-setq (x y) (values y x))     ; swapped here
2
[4]> (list x y)
(2 1)

 

단 한 번의 함수 호출로 변수 x, y 의 값이 교환(swap)되였다.

만일 이를 Python 으로 한다면

>>> x, y = 1, 2
>>> x, y
(1, 2)
>>> x, y = y, x     # swapped here
>>> x, y
(2, 1)

 

Posted by Scripter
,

[파일명:  testStringFindInVector.lsp]------------------------------------------------
#!/usr/bin/env clisp

;; Filename: testStringFindInVector.lsp
;;
;;            Approximate square roots, cubic roots and n-th roots of a given number.
;;
;; Execute: clisp testStringFindInVector.lsp
;;   Or
;; Execute: ./testStringFindInVector.lsp
;;
;; Date: 2013. 9. 12.

(defun my-exact-find(arr s)
    ; (position s arr))
   (let ((r -1))
        (loop for i from 0 below (length arr) do
            (if (string= s (aref arr i))
         (progn
        (setf r i)
     (return i))))
        r))

(defun printArray(arr)
    (format t "[")
    (loop for i from 0 below (- (length arr) 1) do
        (format t "~A, " (aref arr i)))
    (if (plusp (length arr))
        (format t "~A" (aref arr (- (length arr) 1))))
    (format t "]~%"))


(setf *words* (vector "하나" "둘" "셋" "넷" "다섯" "여섯"))
(setf where (my-exact-find *words* "셋"))

(format t "vector: ")
(printArray *words*)
; (format t "where = ~A~%" where)
(if (and where (>= where 0))
    (progn
        (format t "발견! ~%")
        (if (< where (length *words*))
            (format t "Next word of 셋 in vector: ~A~%" (aref *words* (+ where 1))))))

(format t "Sorting...~%")
(sort *words* #'string<)

(setf where (my-exact-find *words* "셋"))
(format t "vector: ")
(printArray *words*)
(if (and where (>= where 0))
    (progn
        (format t "발견! ~%")
        (if (< where (length *words*))
            (format t "Next word of 셋 in vector: ~A~%" (aref *words* (+ where 1))))))

#|
Output:
vector: [하나, 둘, 셋, 넷, 다섯, 여섯]
발견!
Next word of 셋 in vector: 넷
Sorting...
vector: [넷, 다섯, 둘, 셋, 여섯, 하나]
발견!
Next word of 셋 in vector: 여섯
|#
------------------------------------------------



Posted by Scripter
,

역삼각함수란 삼각함수의 역함수를 의미하고,

역쌍곡선함수란 쌍곡선함수의 역함수를 의미한다.

수학에서 sin 함수의 역함수는 arcsin 으로 표기되는데, Common Lisp 언어에서는 asin 함수로 이미 구현되어 있다. 마찬가지로 쌍곡선 함수 sihh cosh 들의 역함수들도 각각 asinh, acosh 라는  이름으로 이미 구현되어 있다.

 

#!~/usr/bin/env clisp

;; Filename: testArcSine.lsp
;;
;; Execute: clisp testArcSine.lsp
;;  Or
;; Execute: ./testArcSine.lsp
;;
;; Date: 2013. 9. 12.

#|
def asinh(x):
            y = math.log(x + math.sqrt(x*x + 1))
            return y

def acosh(x):
            y = math.log(x + math.sqrt(x*x - 1))
            return y
|#


(format t "Using the type of float, ~%")
(setf x -0.9)
(setf y (asin x))
(format t "  y = asin(~,1f) = ~,9f~%" x y)
(format t "  sin(y) = sin(~,9f) = ~,1f~%" y (sin y))
           
(setf x 1.1)
(setf u (acosh x))
(setf v (asinh x))
(format t "  u = acosh(~,1f) = ~,9f~%" x u)
(format t "  v = asinh(~,1f) = ~,9f~%" x v)
(format t "  cosh(u) = cosh(~,9f) = ~,1f~%" u (cosh u))
(format t "  sinh(u) = sinh(~,9f) = ~,1f~%" v (sinh v))
(format t "~%")

(format t "Using the type of short-float, ~%")
(setf x -0.9S0)
(setf y (asin x))
(format t "  y = asin(~f) = ~f~%" x y)
(format t "  sin(y) = sin(~f) = ~f~%" y (sin y))
           
(setf x 1.1S0)
(setf u (acosh x))
(setf v (asinh x))
(format t "  u = acosh(~f) = ~f~%" x u)
(format t "  v = asinh(~f) = ~f~%" x v)
(format t "  cosh(u) = cosh(~f) = ~f~%" u (cosh u))
(format t "  sinh(u) = sinh(~f) = ~f~%" v (sinh v))
(format t "~%")
           
(format t "Using the type of double-float, ~%")
(setf x -0.9D0)
(setf y (asin x))
(format t "  y = asin(~f) = ~f~%" x y)
(format t "  sin(y) = sin(~f) = ~f~%" y (sin y))
           
(setf x 1.1D0)
(setf u (acosh x))
(setf v (asinh x))
(format t "  u = acosh(~f) = ~f~%" x u)
(format t "  v = asinh(~f) = ~f~%" x v)
(format t "  cosh(u) = cosh(~f) = ~f~%" u (cosh u))
(format t "  sinh(u) = sinh(~f) = ~f~%" v (sinh v))
(format t "~%")
           
(format t "Using the type of long-float, ~%")
(setf x -0.9L0)
(setf y (asin x))
(format t "  y = asin(~f) = ~f~%" x y)
(format t "  sin(y) = sin(~f) = ~f~%" y (sin y))
           
(setf x 1.1L0)
(setf u (acosh x))
(setf v (asinh x))
(format t "  u = acosh(~f) = ~f~%" x u)
(format t "  v = asinh(~f) = ~f~%" x v)
(format t "  cosh(u) = cosh(~f) = ~f~%" u (cosh u))
(format t "  sinh(u) = sinh(~f) = ~f~%" v (sinh v))
(format t "~%")
           
#|
Output:
Using the type of float,
  y = asin(-0.9) = -1.119769600
  sin(y) = sin(-1.119769600) = -0.9
  u = acosh(1.1) = 0.443568350
  v = asinh(1.1) = 0.950346950
  cosh(u) = cosh(0.443568350) = 1.1
  sinh(u) = sinh(0.950346950) = 1.1

Using the type of short-float,
  y = asin(-0.9) = -1.11978
  sin(y) = sin(-1.11978) = -0.9
  u = acosh(1.1) = 0.443573
  v = asinh(1.1) = 0.95035
  cosh(u) = cosh(0.443573) = 1.1
  sinh(u) = sinh(0.95035) = 1.1

Using the type of double-float,
  y = asin(-0.9) = -1.1197695149986342
  sin(y) = sin(-1.1197695149986342) = -0.9
  u = acosh(1.1) = 0.4435682543851155
  v = asinh(1.1) = 0.9503469298211343
  cosh(u) = cosh(0.4435682543851155) = 1.1
  sinh(u) = sinh(0.9503469298211343) = 1.1

Using the type of long-float,
  y = asin(-0.9) = -1.1197695149986341867
  sin(y) = sin(-1.1197695149986341867) = -0.90000000000000000003
  u = acosh(1.1) = 0.44356825438511518925
  v = asinh(1.1) = 0.95034692982113425026
  cosh(u) = cosh(0.44356825438511518925) = 1.1
  sinh(u) = sinh(0.95034692982113425026) = 1.1
|#

 

 

 

Posted by Scripter
,

Lanczos 알고리즘은 Stirlng 공식에 의한 알고리즘 보다 정밀하며, 십진수로 유효숫자 약 15자리 까지는 정확하게 계산해 준다.  단지 exp 함수를 이용하는 부분에서는 exp 함수의 구현에 따라 오차가 더 있을 수 있다. 단, Common Lisp 언어의 float 타입은 유효숫자를 약 7개~8개 밖에 알아내지 못한다.


Comon Lisp 언어의 디퐁트 부동소수점수는 단정밀도 부동소수점수이다. 단정밀도 부동소수점수는 그 처리 가능한 양수의 범위가 최소 2−126 ≈ 1.18 × 10−38 부터 최대  (2−2−23) × 2127 ≈ 3.4 × 1038 밖에 되지 않는다. 이 범위를 벗어나는 양수에 대해서는 overflow 에러가 나게 마련이다.

이런 이유로 100! 을 계산하기 위해 (gamma 101) 하면 floating point overflow 에러가 발생한다. 아래의 소스에서 (gamma 101) 을 구하는 부분을  ignore-errors 로 처리한 것은 floating point overflow 에러가 나서 실행이 멈추는 것을 방지하기 위함이다.

 

#!/usr/bin/env clisp

;; Filename: testLanczos-01.lsp
;;
;;           An approximation for the gamma function by using the Lanczos algorithm
;;
;; Execute: clisp testLanczos-01.lsp
;;         or
;; Execute: ./testLanczos-01.lsp
;;
;; See: http://en.wikipedia.org/wiki/Lanczos_approximation
;; See:http://www-history.mcs.st-and.ac.uk/Biographies/Lanczos.html
;; See: http://www.thinbasic.com/community/showthread.php?11279-Gamma-function

 
;; Coefficients used by the GNU Scientific Library
(setf *g* 7)
(setf *p* (list
            0.99999999999980993   676.5203681218851       -1259.1392167224028
          771.32342877765313     -176.61502916214059         12.507343278686905
           -0.13857109526572012     9.9843695780195716e-6    1.5056327351493116e-7) )
 
(defun gamma(z)
    (let ((tt (complex 0.0 0.0)))
        (if (realp z) (setf z (complex z 0.0)))
        ;; Reflection formula
        (if (< (realpart z) 0.5)
            (/ pi (sin (* (* pi z) (gamma (- 1 z)))))
            (progn
                (setf z (- z 1))
                (setf x (nth 0 *p*))
                (loop for i from 1 below (+ *g* 2) do
                    (setf x (+ x (/ (nth i *p*) (+ z i)))))
                (setf tt (+ z *g* 0.5))
                (* (sqrt (* 2 pi)) (expt tt (+ z 0.5)) (exp (- tt)) x) ))))

(defun factorial(n)
    (let ((k 0))
        (if (< n 2)
            1
            (progn
                (setf k 1)
                (if (evenp n)
                    (loop for i from 0 below (floor (/ n 2)) do
                        (setf k (* k (* (+ i 1) (- n i)))))
                    (progn
                        (loop for i from 0 below (floor (/ n 2)) do
                            (setf k (* k (* (+ i 1) (- n 1 i)))))
                        (setf k (* k n))))
                k))))

(defun facto(n)
    (let ((k 0))
        (if (< n 2)
            1
            (progn
                (setf k 1)
                (loop for i from 2 to n do
                    (setf k (* k i)) )
                k ))))

;; Begin here
(format t "gamma(10) = 9! = ~A asymptotically~%" (gamma 10))

(format t "gamma(21) = 20! = ~16A asymptotically~%" (gamma 21))
(format t "gamma(21) = 20! = ~16G asymptotically~%" (gamma 21))
(format t "gamma(21) = 20! = ~16G asymptotically~%" (realpart (gamma 21)))
(format t "gamma(21) = 20! = ~16F asymptotically~%" (gamma 21))
(format t "gamma(21) = 20! = ~16F asymptotically~%" (realpart (gamma 21)))
; (format t "gamma(101) = 100! = ~16A asymptotically~%" (gamma 101))
;; "{0.real:.15f}{0.imag:+.5f}j".format(gamma(101))

(ignore-errors
    (format t "gamma(101) = 100! = ~16A asymptotically~%" (gamma 101))
)

(setf i 10)
(format t "factorial(~D) = ~D! = ~D~%"  i i (factorial i))
(format t "facto(~D) = ~D! = ~D~%"  i i (facto i))

(setf i 20)
(format t "factorial(~D) = ~D! = ~D~%"  i i (factorial i))
(format t "facto(~D) = ~D! = ~D~%"  i i (facto i))

(setf i 100)
(format t "factorial(~D) = ~D! = ~D~%"  i i (factorial i))
(format t "facto(~D) = ~D! = ~D~%"  i i (facto i))


#|
if __name__ == "__main__":
    print "gamma(10) = 9! = %s asymptotically" % gamma(10)
    # print "gamma(101) = 100! = %16s asymptotically" % gamma(101)
    print "gamma(101) = 100! = %16s asymptotically" % "{0.real:.15f}{0.imag:+.5f}j".format(gamma(101))

    for i in range(11):
        print "%d! = %d" % (i, factorial(i))

    i = 100
    print "factorial(%d) = %d! = %d" % (i, i, factorial(i))
    print "facto(%d) = %d! = %d" % (i, i, facto(i))
|#

#|
Output:
gamma(10) = 9! = #C(362880.16 0.0) asymptotically
gamma(21) = 20! = #C(2.4329015E18 0.0) asymptotically
gamma(21) = 20! = #C(2.4329015E18 0.0) asymptotically
gamma(21) = 20! = 2432901500000000000.     asymptotically
gamma(21) = 20! = #C(2.4329015E18 0.0) asymptotically
gamma(21) = 20! = 2432901500000000000. asymptotically
factorial(10) = 10! = 3628800
facto(10) = 10! = 3628800
factorial(20) = 20! = 2432902008176640000
facto(20) = 20! = 2432902008176640000
factorial(100) = 100! = 93326215443944152681699238856266700490715968264381621468
59296389521759999322991560894146397615651828625369792082722375825118521091686400
0000000000000000000000
facto(100) = 100! = 933262154439441526816992388562667004907159682643816214685929
63895217599993229915608941463976156518286253697920827223758251185210916864000000
000000000000000000
|#

 

GNU CLisp 에서는 네가지 타입의 부동소수점수

             short-float, single-float, double-float, long-float

들을 지원한다. clisp 를 대화형 모드로 실행하여 간단한 테스트를 해보자.

 

명령프롬프트> clisp
  i i i i i i i       ooooo    o        ooooooo   ooooo   ooooo
  I I I I I I I      8     8   8           8     8     o  8    8
  I  \ `+' /  I      8         8           8     8        8    8
   \  `-+-'  /       8         8           8      ooooo   8oooo
    `-__|__-'        8         8           8           8  8
        |            8     o   8           8     o     8  8
  ------+------       ooooo    8oooooo  ooo8ooo   ooooo   8

Welcome to GNU CLISP 2.49 (2010-07-07) <http://clisp.cons.org/>

Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2010

Type :h and hit Enter for context help.

[1]> pi
3.1415926535897932385L0
[2]> (/ 1 3)
1/3
[3]> (+ (/ 1 3) 0.0)
0.33333334
[4]> (coerce (/ 1 3) 'double-float)
0.3333333333333333d0
[5]> (coerce (/ 1 3) 'long-float)
0.33333333333333333334L0
[6]> (defun double-float(x)
    (coerce x 'double-float))
DOUBLE-FLOAT
[7]> (double-float (/ 1 3))
0.3333333333333333d0
[8]> (defun long-float(x)
    (coerce x 'long-float))
LONG-FLOAT
[9]> (long-float (/ 1 3))
0.33333333333333333334L0
[10]> (quit)
Bye.

 

 

#!/usr/bin/env clisp

;; Filename: testLanczos-02.lsp
;;
;;           An approximation for the gamma function by using the Lanczos algorithm
;;
;; Execute: clisp testLanczos-02.lsp
;;         or
;; Execute: ./testLanczos-02.lsp
;;
;; See: http://en.wikipedia.org/wiki/Lanczos_approximation
;; See:http://www-history.mcs.st-and.ac.uk/Biographies/Lanczos.html
;; See: http://www.thinbasic.com/community/showthread.php?11279-Gamma-function

 
;; Coefficients used by the GNU Scientific Library
(setf *g* 7)
(setf *p* (list
            0.99999999999980993L0   676.5203681218851L0       -1259.1392167224028L0
          771.32342877765313L0     -176.61502916214059L0         12.507343278686905L0
           -0.13857109526572012L0     9.9843695780195716L-6    1.5056327351493116L-7) )
 
(defun gamma(z)
    (let ((z (coerce z 'long-float))
          (tt (complex 0.0L0 0.0L0)))
        (if (realp z) (setf z (complex z 0.0L0)))
        ;; Reflection formula
        (if (< (realpart z) 0.5L0)
            (/ pi (sin (* (* pi z) (gamma (- 1L0 z)))))
            (progn
                (setf z (- z 1))
                (setf x (nth 0 *p*))
                (loop for i from 1 below (+ *g* 2) do
                    (setf x (+ x (/ (nth i *p*) (+ z i)))))
                (setf tt (+ z *g* 0.5L0))
                (* (sqrt (* 2L0 pi)) (expt tt (+ z 0.5L0)) (exp (- tt)) x) ))))

(defun factorial(n)
    (let ((k 0))
        (if (< n 2)
            1
            (progn
                (setf k 1)
                (if (evenp n)
                    (loop for i from 0 below (floor (/ n 2)) do
                        (setf k (* k (* (+ i 1) (- n i)))))
                    (progn
                        (loop for i from 0 below (floor (/ n 2)) do
                            (setf k (* k (* (+ i 1) (- n 1 i)))))
                        (setf k (* k n))))
                k))))

(defun facto(n)
    (let ((k 0))
        (if (< n 2)
            1
            (progn
                (setf k 1)
                (loop for i from 2 to n do
                    (setf k (* k i)) )
                k ))))

;; Begin here
(format t "gamma(10) = 9! = ~A asymptotically~%" (gamma 10))

(format t "gamma(21) = 20! = ~16A asymptotically~%" (gamma 21))
(format t "gamma(21) = 20! = ~16G asymptotically~%" (gamma 21))
(format t "gamma(21) = 20! = ~16G asymptotically~%" (realpart (gamma 21)))
(format t "gamma(21) = 20! = ~16F asymptotically~%" (gamma 21))
(format t "gamma(21) = 20! = ~16F asymptotically~%" (realpart (gamma 21)))
; (format t "gamma(101) = 100! = ~16A asymptotically~%" (gamma 101))
;; "{0.real:.15f}{0.imag:+.5f}j".format(gamma(101))

(ignore-errors
    (format t "gamma(101) = 100! = ~16A asymptotically~%" (gamma 101))
)

(format t "tgamma(~D) = ~D! = ~D~%"  101 100 (tgamma 101))

(setf i 10)
(format t "factorial(~D) = ~D! = ~D~%"  i i (factorial i))
(format t "facto(~D) = ~D! = ~D~%"  i i (facto i))

(setf i 20)
(format t "factorial(~D) = ~D! = ~D~%"  i i (factorial i))
(format t "facto(~D) = ~D! = ~D~%"  i i (facto i))

(setf i 100)
(format t "factorial(~D) = ~D! = ~D~%"  i i (factorial i))
(format t "facto(~D) = ~D! = ~D~%"  i i (facto i))

 

#|
Output:
gamma(10) = 9! = #C(362880.0000000007251L0 0.0L0) asymptotically
gamma(21) = 20! = #C(2.4329020081766424835L18 0.0L0) asymptotically
gamma(21) = 20! = #C(2.4329020081766424835L18 0.0L0) asymptotically
gamma(21) = 20! = 2432902008176642483.5     asymptotically
gamma(21) = 20! = #C(2.4329020081766424835L18 0.0L0) asymptotically
gamma(21) = 20! = 2432902008176642484. asymptotically
gamma(101) = 100! = #C(9.332621544393798272L157 0.0L0) asymptotically
tgamma(101) = 100! = 9.332621544394416d157
factorial(10) = 10! = 3628800
facto(10) = 10! = 3628800
factorial(20) = 20! = 2432902008176640000
facto(20) = 20! = 2432902008176640000
factorial(100) = 100! = 93326215443944152681699238856266700490715968264381621468
59296389521759999322991560894146397615651828625369792082722375825118521091686400
0000000000000000000000
facto(100) = 100! = 933262154439441526816992388562667004907159682643816214685929
63895217599993229915608941463976156518286253697920827223758251185210916864000000
000000000000000000
|#

 

 

 

Posted by Scripter
,