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


[표 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 살레시오
,