맥시마는 내부적으로 미리 정의된 수학 상수들이 있는데 다음 표와 같다.


[표 1] 맥시마의 내부 상수들

기호

의미

%e

자연 상수 (2.718182…)

%pi

원주율 ( 3.1415…)

%i

허수

true, false

참, 거짓

%gamma

Euler-Mascheroni constant, 0.577215…

%phi

황금율 (1+sqrt(5))/2

_ (언더바)

직전 입력

%

직전 출력

inf, minf, infinity

+무한대, -무한대, 무한 복소수

zeroa, zerob

무한소 (infinitesimal above/below zero)

ind

부정수 (indefinite number)

und

undefined number


이 표에 있는 상수 중에서 %e, %i, %pi는 특히 많이 쓰이니 꼭 숙지해야 하며, 입력할 때 %기호를 빠뜨리기 쉬우니 주의해야 한다.


 복소수를 입력하는 것은 허수 %i를 이용한다.



첫 번째는 3i 를 입력한 것이고 두 번째는 복소수 4-5i 를 생성하여 변수 a에 대입하는 것이다. 5와 %i 사이의 곱(*) 기호를 빠뜨리면 안된다.


 지수함수 ex를 입력하는데 %e 상수를 이용할수도 있고 exp(x)함수를 이용할 수 도 있다. 두 방법은 동일하다.



 어떤 상수의 실수 근사값을 알고 싶다면 float()함수를 이용하거나 ‘, numer’ 명령을 이용한다.




Posted by 살레시오

댓글을 달아 주세요

기본적인 연산자

 다음 표에 기본적인 Scilab연산자를 정리하였다. Scilab의 기본 객체는 ‘행렬’이므로 피연산자도 일반적으로 ‘행렬’이다.


[표 1] 기본 연산자

연산자

기능

+

덧셈(이항연산자), +부호(단항연산자)

-

뺄셈(이항연산자), -부호(단항연산자)

*

곱셈

.*

요소간 곱셈

.*.

Kronercker 곱셈. kron(A,B)와 동일

/

나눗셈

\

역나눗셈 (즉 a\b 는 b를 a로 나눈다)

./

요소간 나눗셈

.\

요소간 역나눗셈

./.

Kronecker 나눗셈

.\.

Kronecker 역나눗셈

^ 또는 **

거듭 제곱

.^

요소간 거듭 제곱

‘(작은따옴표)

복소 전치 행렬

.’(점작은따옴표)

단순 전치 행렬


이 표에서 보면 요소간 연산자가 있는데 이것은 행렬 간 연산에서 같은 요소끼리의 연산을 수행한다. 예를 들어서 두 행렬 A, B에 대해서 A*B는 보통의 행렬곱으로 A의 열수와 B의 행수가 같아야 성랍하지만 A.*B 는 같은 위치의 요소끼리 곱셈을 수행하므로 A와 B의 크기가 같아서 수행된다. 예제는 행렬에 대해서 알아볼 때 들겠다.


 대입문을 작성할 때 tuple을 사용하여 한 번에 여러 변수를 지정하는 것이 가능하다. tuple 은 괄호 ( ) 를 사용하는데 각각의 요소는 반드시 comma (,)로 구분해야 한다. 이 기능을 사용하면 변수들을 서로 swap하는 데도 간결하게 사용할 수 있다.(이 기능은 python과 흡사하다.)


 아래에서 첫 번째 예가 변수 u, v 그리고 w 를 동시에 생성하는 것이다. 좌변에는 [ ... ] 를 우변에서 tuple을 지정할 때는 ( ... ) 를 사용했음에 유의해야 한다, 두 번째 예는 u와 v의 값을 서로 맞바꾸는 것이다.

내부 상수들

 다음 표에 미리 정의되어 사용되는 내부 상수들을 정리하였다. 이 변수들은 모두 %로 시작하며 사용자가 덮어 쓸 수 없다.(즉, 재정의될 수 없다.)


[표 2] Scilab의 기정의된 내부 상수들

변수명

의미

%i

허수 ()

%e

자연상수 (2.718281…)

%pi

원주율 (3.142592…)

%eps

표현가능한 가장 작은 수(약 2.2e-16)

%inf

무한대

%nan

not a number

%t or %T

(논리적) 참

%f or %F

(논리적) 거짓

%s

다항식 s=poly(0,’s’)

%z

다항식 s=poly(0,’z’)

%io

표준 I/O

Scilab의 식별자에서 ‘%’를 사용할 수 있는데 맨 첫자로만 사용가능하다. 따라서 위의 상수들은 모두 특정 값이 저장되어 있고 변경할 수 없는 변수와 같이 취급된다.



Posted by 살레시오

댓글을 달아 주세요

 AVR의 SRAM의 메모리 공간은 매우 제한적이기 때문에 다량의 상수 데이터를 SRAM에 저장하여 메모리를 차지하는 것보다 플래시롬에 저장하는 것이 효율적일 수 있다. 플래시롬에 저장된 데이터는 런타임에는 수정될 수 없으므로 상수(즉, 고정된 값)만을 저장해야만 한다. 예를 들어 문자열이라든가, 아니면 크기가 큰 배열을 저장할 때는 플래시롬를 이용할 수 있다.


 플래시롬을 접근하는데 필요한 기능들은 <avr/pgmspace.h>에 정의되어 있으므로 이 헤더파일을 인클루드해줘야 한다. 그리고 사용하는 AVR이 어셈블리명령어인 LPM 혹은 ELPM을 지원하여야 한다. LPM/ELPM은 플래쉬메모리에서 데이터를 레지스터로 읽어오는 동작을 하는 어셈블리 명령어로서 ATmega8A는 LPM명령이 존재한다.


#include <avr/pgmspace.h>


플래시 메모리에 저장될 데이터는 전역 상수로 정의되어야 하며 변수 선언과 동시에 초기화를 해주어야 한다. 그리고 변수의 타잎지정자 뒤에 PROGMEM (스펠링에 주의할 것) 이라는 키워드를 추가하면 된다. 최신 버전의 AVR툴체인에서는 컴파일할 때 경고를 없애기 위해서 반드시 const 키워드를 추가시켜야 한다.


#include <avr/io.h>
#include <avr/pgmspace.h>
const signed char cA PROGMEM = -1;
const unsigned char cB PROGMEM = -1;
const signed int iA PROGMEM = -1;
const unsigned int iB PROGMEM = -1;
const float fA PROGMEM = -1;
const unsigned char cArr[5] PROGMEM =
{0x01,0x02,0x03,0x04,0x05};


 한 가지 주의할 점은 이렇게 저장된 데이터를 읽어내려면 일반 변수와 같이 사용할 수는 없으며 별도로 정의된 다음과 같은 함수들을 사용해야 한다는 점이다.


pgm_read_byte(<pointer>)
pgm_read_word(<pointer>)
pgm_read_dword(<pointer>)
pgm_read_float(<pointer>)

예를 들어서 위의 예에서 cA값을 다른 변수에 저장하려면 다음과 같이 해야 한다.


signed char cX;
cX = pgm_read_byte(&cA);// cX = cA 는 안 됨.


또는 cArr배열의 세번째 요소를 읽어들이려면 다음과 같이 사용한다.


unsigned char cY;
cY = pgm_read_byte(cArr+2); //cY = cArr[2] 는 안 됨


또한 <pgmspace.h>에서는 PSTR()이라는 간결한 매크로가 정의되어 있는데 이 매크로는 플래시메모리에 문자열을 저장하고 그 포인터를 반환한다. 이 경우에는 궂이 전역 변수로 정의할 필요는 없으며 포인터이기 때문에 지역 변수로도 사용할 수 있다.


int main(void) {
   const char *str = PSTR("Hello world!");
   LCD_puts(str);
}


또는 다음와 같이 한 줄로도 줄일 수 있으므로 매우 간편하게 사용할 수 있다. 단, 위의 경우는 포인터 변수 str을 당연히 함수 내부의 여러 곳에서 사용할 수 있으나 다음의 경우는 단 한 번만 사용가능하다.


LCD_puts( PSTR("Hello! world") );


즉, "Hello! world"라는 문자열은 PSTR()이라는 매크로에 의해서 플래시메모리에 저장되고 그 포인터를 반환하여 LCD_puts()라는 함수에서 사용되는 것이다.

 이전 버젼의 WinAVR에서는 [표 1]에 기술한 바와 같이 pgmspace.h에서 typedef명령으로 정의된 별도의 데이터 타잎을 사용할 수 있다. 하지만 Atmel Studio 6.x버젼에 포함된 툴체인에서는 이러한 사용법을 더 이상 권장하지 않고 앞으로 사라질 것이라고 <avr/pgmspace.h>에 기술되어 있다. 단, 이전 프로그램과의 호환성때문에 이러한 데이터형을 사용할 경우에는 <avr/pgmspace.h>를 인클루드하기 전에 상수 __PROG_TYPES_COMPAT__ 를 정의하여야 한다.


[표 1] 플래시롬 상수의 자료형 (권장하지 않음)

자료형

byte

표현 범위

비고

prog_char or prog_int8_t

1

signed char

prog_uchar or prog_uint8_t

1

unsigned char

prog_int16_t

2

signed int

prog_uint16_t

2

unsigned int

prog_int32_t

3

signed long

prog_uint32_t

3

unsigned long

prog_int64_t

4

signed long long

prog_uint64_t

5

unsigned long long


위의 도표에 기술된 데이터 타잎을 사용하는 예는 다음과 같다.


#define __PROG_TYPES_COMPAT__ //반드시 있어야 함.
#include <avr/pgmspace.h>
const prog_char cA = -1;
const prog_uchar cB = 1;
const prog_int16_t iA = -1;
const prog_uint16_t iB = 1;


하지만 전술한 바와 같이 이 방법은 더 이상 사용하지 않는 것이 바람직하다.



Posted by 살레시오

댓글을 달아 주세요

 #define은 상수를 이름으로 정의하거나 매크로 함수를 정의할 때 사용하는 전처리문이다. (전처리문이란 컴파일을 수행 하기 전 소스 코드를 변환시켜주는 명령어들을 말한다.)  #define을 잘 활용하면 가독성이 향상된 프로그램을 만들 수 있고 프로그램을 수정하기에 효율적으로 작성할 수 있다. 기본 형식은 다음과 같다.


#define NAME VALUE


NAME은 그 뒤에 있는 숫자를 대신해서 사용할 명칭이다. 맨 끝에 세미콜론(;)이 붙지 않음에 유의하자.

다음 예를 보자.


#include <stdio.h>
#define PI 3.14  // PI를 3.14로 정의
int main() {
   float fR = 3.0;
   printf("radius : %f\n", fR);
   printf("circumference : %f \n", 2*PI*fR);
   printf("area : %f \n", PI*fR*fR);
   printf("volume : %f \n", 4*PI*fR*fR*fR/3);
}


radius : 3.000000
circumference : 18.840000
area : 28.260000
volume : 113.040000


두 번째 줄을 보면 다음과 같이 작성되어 있는데

#define PI 3.14


이것은 3.14라는 실수값을 PI라는 이름으로 사용하겠다는 정의이다. 실제로 프로그램상에서 printf()함수 안에서 사용되었다. 이 코드는 전처리기에 의해서 컴파일 전에 다음과 같이 내부적으로 수정된다.


printf("원의 둘레: %f \n", 2*3.14*fR);
printf("원의 면적: %f \n", 3.14*fR*fR);
printf("구의 체적: %f \n", 4*3.14*fR*fR*fR/3);


따라서 처음부터 직접 위와 같이 작성하나 #define 문을 사용해서 PI라는 기호로 작성하나 내부적으로는 아무런 차이가 없다. 하지만 다른 사람이 볼 때 PI라는 ‘의미를 유추할 수 있는 기호’를 사용하는 것과 3.14라는 숫자를 직접 사용하는 것과는 차이가 있다.


 더 큰 문제는 3.14라는 상수 값을 예를 들어 3.1415로 변경시켜야 할 경우가 발생했을 때이다. 위와 같이 프로그램했을 경우 세 곳을 모두 고쳐야 하지만 #define문을 사용한 경우에는 정의한 곳 한 곳만 고치고 다시 컴파일 해주면 된다. 이 예에는 세 곳이지만 프로그램이 길어진다면 수십 곳, 수백 곳이 될 수도 있을 것이다.

 전술한 바와 같이 #define문으로 상수에 적절한 이름을 부여하는 것은 프로그램의 가독성 측면이나 수정의 용이함 등을 따질 때 그 활용도가 상당히 높다고 할 수 있다.



Posted by 살레시오

댓글을 달아 주세요

 심파이(sympy)에서 미리 정의된 상수들은 다음과 같은 것들이 있다.


[표 1] 심파이의 기정의된 상수들

sympy 상수
의미
I, 1j, 1J
허수. (예를 들어 3+4j 는 3+4*I 와 같이 입력해야 한다.)
pi
원주율(3.141592..)
E
자연상수(2.718281..)
nan
not a number
oo
(positive) infinity
zoo
complex infinity


허수로 I를 이용할 때는 허수부와 I 사이에 반드시 곱기호를 넣어 주어야 한다.


>>> abs(1+2*I)
sqrt(5)


무리수의 근사값을 알고 싶다면 evalf() 멤버함수를 이용하면 된다.


>>> pi.evalf()
3.14159265358979

>>> E.evalf()
2.71828182845905




Posted by 살레시오

댓글을 달아 주세요