산술 연산은 타 프로그래밍 언어에서도  거의 공통적으로 쓰이는 기호가 맥시마에서도 사용된다. 맥시마는 수를 표현하는 방식에서 ‘기호 형식’과 ‘수치 형식’이 있으며 (numer 라는 내부 변수에 의해서 지정됨.) 기본적으로 초기에는 기호 형식으로 동작한다. 이 두 가지 형식의 차이점을 예를 들어서 설명하면 다음과 같다. 기호모드에서는 1/11 이라는 분수를 그냥 분수의 형태로 저장하며 사실 이 수는 이 형태가 정확한 표현인 것이다. 그러나 수치모드에서는 이 숫자를 입력하면 0.090909090909091 와 같이 소수형식으로 표현되며 엄밀히 얘기하면 이 수는 1/11 의 근사값이다. 다음 [표 1]에 Maxima에서 쓰이는 산술연산기호를 정리하였다.

[표 1] 맥시마의 산술 연산자

기호

작업

비고

+

덧셈

※내부 변수 numer 의 진리값에 따라 표시 결과가 다름

-

뺄셈

*

곱셈

/

나눗셈

^

거듭 제곱



똑같은 명령어라도 수치 형식인 경우는 결과가 달라진다. 내부 변수와 변수에 값을 지정하는 방법은 뒤에서 다루어지므로 여기에서는 그냥 결과만 확인하자.



여기에서 numer:true 명령은 numer라는 내부 변수에 true라는 값을 대입하는 것이다. 맥시마는 특이하게 대입 연산자가 콜론(:)이다.


 만약 현재 모드를 바꾸지 않고 특정 수식의 실수 값을 확인하고 싶으면 float()함수를 사용하거나 표현식 뒤에 ‘, numer’라고 추가입력하면 된다.



 산술연산 기호를 이용하면 Maxima에는 대수식이나 방정식과 같은 것들도 쉽게 표현할 수 있다. 만약 x2+2x+1,1/(y2+1)이라는 대수식을 입력하려면 아래와 같이 하면 된다.



 연습 문제로 다음과 같은 식을 입력하고 확인해 보자.



Posted by 살레시오

댓글을 달아 주세요

 여기에서는 행렬-스칼라 그리고 행렬-행렬간의 산술 연산에 대해서 설명을 하겠다. 다음의 예를 보자.


>> G=[1 2 3 4;5 6 7 8]
G =
1 2 3 4
5 6 7 8

>> G-2
-1 0 1 2 3 4 5 6

>> -2+G
-1 0 1 2 3 4 5 6


이 예에서 변수 G는 행렬이고 2는 스칼라이다. 기본적으로 (수학적인) 행렬의 덧셈 뺄셈은 두 행렬의 차수가 같아야 하지만 한쪽이 스칼라이고 다른 한쪽이 행렬이면 행렬의 모든 요소에서 그 스칼라를 더하거나 빼준 행렬을 결과로 내보낸다.


>> 2*G-1 󰎠
1 3 5 7
9 11 13 15


스칼라와 벡터/행렬의 곱은 수학적인 의미 그대로이며 연산 우선순위도 스칼라연산과 같다. 위의 경우 곱을 먼저 행하고 뺄셈을 행하게 된다.


 행렬 간의 덧셈, 뺄셈은 두 연산자의 차수가 같아야 한다. 다음과 같이 행렬 G와 H를 입력해보자.


>> G=[1 2 3 4; 5 6 7 8; 9 10 11 12] 󰎠
G =
1 2 3 4
5 6 7 8
9 10 11 12

>> H=[1 1 1 1;2 2 2 2; 3 3 3 3] 󰎠
H =
1 1 1 1
2 2 2 2
3 3 3 3


그리고 다음과 같이 덧셈, 뺄셈을 수행해 보라.


>> G+H
2 3 4 5
7 8 9 10
12 13 14 15

>> ans-H
1 2 3 4
5 6 7 8
9 10 11 12

>> 2*G-H
1 3 5 7
8 10 12 14
15 17 19 21


 곱셈의 경우 곱셈기호(*)앞의 행렬의 열수와 뒤 행렬의 행수가 같아야 계산이 수행된다. 따라서 위의 두 행렬 G와 H는 곱셈을 할 수 없다. Ht라는 행렬을 다음과 같이 정의하면


>> Ht=h'
Ht =
1 2 3
1 2 3
1 2 3
1 2 3


이제 행렬 G(차원)와 Ht(차원)간의 곱셈은 가능해진다.


>> G*Ht
10 20 30
26 52 78
42 84 126


 다른 연습 예제로서 다음과 같은 행렬 A와 B가 있을 때,

두 행렬의 곱 AB, BA, ATBT, BTAT 를 각각 구해보라.

 MATLAB에서 행렬간의 곱셈은 이와 같은 보통 행렬 간 곱셈뿐만 아니라 행렬 요소 간의 곱셈도 가능하다. 행렬 요소 간 곱셈을 행하는 연산자는 (.*)이고 이 연산자 앞뒤에 오는 피연산자들의 차원은 같아야 한다.


>> G.*H
1 2 3 4
10 12 14 16
27 30 33 36


행렬 간의 나눗셈은 무슨 의미 일까? 예를 들어서


>> A=[1 2;3 4]
A =
1 2
3 4

>> B=[5 6;7 8]
B =
5 6
7 8



와 같이 정의된 정방행렬 A와 B에 대해서 A/B 또는 B\A는 무슨 의미일까? 결과를 확인해 보자.


>> A/B
3.0000 -2.0000
2.0000 -1.0000
>> B\A
5.0000 4.0000
-4.0000 -3.0000


스칼라의 경우를 생각해 보자. 4/3은 4에게 3의 역수를 곱하는 계산 즉, 4x3-1이다. 마찬가지로 3\4은 3의 역수를 4에 곱하는 것(3-1x4)이다. 행렬의 경우도 마찬가지이다. A/B는 행렬 A에 B의 역행렬을 곱하는 것이고, B\A는 B의 역행렬에 A행렬을 곱하는 것이다. 두 결과가 같다고 생각하기 쉽지만  '행렬에서는 교환법칙이 성립하지 않는다'는 것에 유의해야 한다. 위의 결과를 보아도 서로 다르다는 것을 알 수 있다. 즉 A/B와 B\A는 A와 B가 스칼라라면 같은 수이지만 행렬이라면 서로 다른 행렬이 된다.


 MATLAB에서 역행렬을 구하는 함수는 inv()이다. (inverse 의 줄임말을 함수명으로 채용)


>> A*inv(B)
3.0000 -2.0000
2.0000 -1.0000

>> inv(B)*A
5.0000 4.0000
-4.0000 -3.0000


위의 결과와 이전의 그것과 같다는 것을 알 수 있다. 여기서는 정방행렬의 경우만 다루고 있는데 정방행렬이 아닌 행렬의 가역행렬(pseudo-inverse matrix)를 구하는 함수로 pinv()가 있다. 이에 대해서는 다음에 다루도록 한다.


 나눗셈의 경우도 행렬 요소간 나눗셈이 가능하다. 연산자(./)와 (.\)가 바로 그러한 역할을 한다.


>> A./B 󰎠
0.2000 0.3333
0.4286 0.5000

>> B.\A 󰎠
0.2000 0.3333
0.4286 0.5000


요소 간 연산인 경우에는 항상 두피연산자의 차수가 같아야 한다. 위의 결과를 보면 A./B와 B.\A의 계산결과는 같다는 것을 알 수 있다.(왜일까?)


 행렬의 거듭제곱을 구하는 데는 (^)연산자가 사용되며 행렬의 요소 각각의 거듭제곱을 구하는 데는 (.^)연산자가 사용된다.


>> A^2
7 10
15 22

>> A.^2
1 4
9 16

>> A.^-1
1.0000 0.5000
0.3333 0.2500

>> 2.^A
2 4
8 16

>> A.^B
1 64
2187 65536


이 예에서 A^2과 A.^2 그리고 2.^A의 차이를 확실히 구별해야 한다. 곱셈(*)과 나눗셈(/혹은\) 그리고 거듭제곱(^)을 수행하는 연산자 앞에 ‘점(.)이 붙으면 요소간 연산’이라는 사실을 기억해야 한다.



Posted by 살레시오

댓글을 달아 주세요

 파이썬의 산술 연산자는 다음과 같은 것들이 있다.


[표 1] 파이썬의 산술 연산자들

연산자

기능

비고/용례

+

덧셈

11+22, a+12, a+b

-

뺄셈

11-22j - 33, a-12, a-b

*

곱셈

11*22, (33+44j)*(55-66j), a*b

/

나눗셈

결과는 실수형이다. (2.x에서는 int / int의 결과는 int)

//

자리내림 나눗셈

피연산자가 모두 정수인 경우 나눗셈의 결과 소수점 아래는 버리고 정수만 취한다.

둘 중 하나라도 실수라면 / 연산자와 동일함.

**

거듭제곱

2**10, (1+2j)**20

%

나머지

3%4, -10%3, 12.345%0.4


여기서 나눗셈의 경우 버전에 따라서 결과가 다르다. 2.x버전에서는 정수간 나눗셈의 결과는 정수였다. 즉 1/2는 0, 2/3은 1이다. 하지만 3.x버전에서는 정수간 나눗셈의 결과는 나누어 떨어지는 경우라도 무조건 실수형이 된다. 즉, 1/2는 0.2, 6/3은 2.0이 된다. 다음 결과를 확인해 보자.


>>> 4/5
>>> a,b = 11,5 #a에 11, b에 5를 대입한다.
>>> b/a


2.x버전에서는 정수끼리의 나눗셈의 결과는 정수라는 것에 유의해야 한다.


 연산자 //는 두 피연산자가 모두 정수일 경우 결과값이 실수이면 소수점 아래는 버린다.


>>> 9//2 # 결과는 4 (정수)

>>> 9//2.0 # 결과는 4.5(실수)


 연산자 %는 나눗셈 수행 후 정수몫을 구하고 난 나머지를 구하는 연산자이다. 다음을 확인해보라.


>>> 3%2
1
>>> 11.5%0.2
0.09999999999999937
>>> 11.5%0.3
0.10000000000000042


실수 연산의 경우는 결과값이 정확하지 않을 수도 있다.


 연산자 **는 거듭제곱 연산자이다. 다음 연산의 예를 보자.


>>> 2**10
1024
>>> a,c = 3,4+5j
>>> c**a
(-236+115j)
>>> a**c
(57.00434317675227-57.54567628403595j)


위에서 복소수의 거듭제곱 c**a 는  (4+5j)*(4+5j)*(4+5j) 의 결과값을 보여준다. 파이썬에서는 복소수에 대한 산술 연산도 기본적으로 지원하므로 쉽게 수행할 수 있음을 알 수 있다.


---- (이하 생략 가능) --------------------------------------------------------------------------


 그렇다면 a**c는 왜 저런 결과가 나왔을까? 다음과 같이 오일러(Euler)공식을 이용하면 된다.



이 식의 결과와 위 예제의 결과는 동일하다.



Posted by 살레시오

댓글을 달아 주세요

3.2 산술연산자와 부호연산자    [DOC]    [SMTS]

 산술 연산자는 덧셈, 뺄셈 등 산술 연산을 수행하는 연산자들이고 부호 연산자는 부호를 지정하는 것들이다. 산술 연산자는 피연산자가 두 개이므로 이항 연산자이고 부호 연산자는 피연산자가 하나이므로 단항 연산자에 해당된다.


 사칙 연산자 +, -, *, /, % 는 덧셈, 뺄셈, 곱셈, 나눗셈 그리고 나눗셈의 나머지를 구하는 연산을 수행하는 이항 연산자이다. 예를 들면 다음과 같다.


int ia = 11, ib = 22, ic, id, ie;
ic = 1a + ib;
id = ia – ib;
ie = ia * ib;
double da = 1.1, db=2.2;
da = ie*ie;
db = da/ia;

 부호 연산자는 어떤 값의 부호를 지정하거나 바꾸는데 쓰인다. 여기서 +, -기호는 부호 연산자로도 사용되며, 부호 연산자는 한 개의 피연산자를 요구하는 단항 연산자이다.  예를 들면 다음과 같다.


+1234   -1234   -temp   +a   -b

따라서 다음과 같은 표현식에서 첫 번째 ‘-’는 부호연산자이고 두번째 ‘-’는 산술연산자이다.


ia = -ib - ic;

연산의 결과를 변수에 저장할 때는 결과 값이 그 변수의 허용 범위에 들어가는지 여부를 잘 판단해야 한다.


int ia = 2000000;
int ib = ia*10;
char ca = 129; // 오류
unsigned short usa = 50000, usb;
usb = usa + 20000; // 오류 발생

 나머지(%)연산의 예를 들면 다음과 같다.


10%5 // 0
3%2 // 1
8%3 // 2
3%5 // 3

한 가지 주의할 점은 %연산자의 피연산자는 정수형만 가능하다는 점이다. 예를 들어서,


a = b % c

는 변수 a에 변수 b값을 c로 나눈 나머지를 대입하는 것인데 변수 b와 변수 c는 정수형(char, short, int, long, long long과 각각의 unsigned 형)이어야 한다는 것이다.


다음 예제는 사용자로부터 하나의 숫자를 입력받아서 2로 나눈 나머지를 출력해 주는 프로그램이다.


ex03-01.c
#include <stdio.h>
int main(int argc, char** argv)
{
  int ia;
  scanf("%d", &ia); //정수를 입력받는다.
  printf("result:%d", ia%2);
}

실행 결과

123
result:1

이 예제에서 scanf()함수는 전에 설명한 대로 사용자로부터 입력을 받는 기능을 한다.  첫 번째 인수로 “%d”로 지정하면 정수를, “%f”로 지정하면 실수를 입력받아서 그 뒤의 변수에 그 값을 저장한다. 변수명 앞에 변수의 주소를 구하는 ‘&’를 꼭 붙여야 되므로 유의하자.


다음 예제는 두 수를 입력받아서 덧셈, 뺄셈, 곱셈, 나눗셈의 결과를 표시해 주는 프로그램이다.


ex03-02.c
#include <stdio.h>
int main(int argc, char** argv)
{
  float fa, fb;
  scanf("%f %f",&fa ,&fb); //두 수를 입력받는다.
  printf("fa+fb=%f\n", fa+fb);
  printf("fa-fb=%f\n", fa-fb);
  printf("fa*fb=%f\n", fa*fb);
  printf("fa/fb=%f\n", fa/fb);
}

1e5
12.34
fa+fb=100012.340000
fa-fb=99987.660000
fa*fb=1234000.015259
fa/fb=8103.727615

키보드로 숫자들을 입력할 때 공백 문자(스페이스바 혹은 엔터키)로 두 수를 입력해야 함에 유의하자.


 변수를 사용할 때에는 항상 저장할 수 있는 범위를 고려하여야 한다. 또한 나눗셈의 경우 0으로 나누는 경우가 발생하지 않는지 검토해 보아야 한다. 다음 예제를 실행시켜 보자. (변수명을 타이핑 할 때 대소문자를 반드시 정확히 입력해야 한다.)


ex03-03.c
#include <stdio.h>
int main(void)
{
   char cA = 123, cB = 10, cC = -100, cR1, cR2;
   unsigned char ucW = 110, ucX = 100, ucY = 200;
   unsigned char ucR1, ucR2;
   short sA = 1234, sB = 100, sR1, sR2;
   cR1 = cA + cB + cC;
   cR2 = cA / cB;
   ucR1 = ucW - ucY;
   ucR2 = ucX * ucY;
   sR1 = sA/sB;
   sR2 = sA%sB;
   printf("cR1=%d, cR2=%d\n", cR1, cR2);
   printf("ucR1=%d, ucR2=%d\n", ucR1, ucR2);
   printf("sR1=%d, sR2=%d\n", sR1, sR2);
}

실행 결과

cR1=33, cR2=12
ucR1=166, ucR2=32
sR1=12, sR2=34

이 예제에서는 ucR1과 ucR2 변수의 결과값이 unsigned char형의 범위를 벗어나므로 엉뚱한 값이 표시됨을 눈여겨봐야 한다.


'프로그래밍언어.Lib > C,C++' 카테고리의 다른 글

C/C++의 논리 연산자  (0) 2015.05.19
3.4 관계 연산자  (0) 2015.05.19
3.2 산술 연산자와 부호 연산자  (0) 2015.05.19
3.3 형변환  (0) 2015.05.19
C/C++의 연산자 종류  (0) 2015.05.19
C/C++의 goto 명령  (0) 2015.05.19
Posted by 살레시오

댓글을 달아 주세요

3.3 형변환    [DOC]    [SMTS]

 산술 연산에서 한 가지 주의할 점은 두 피연산자의 자료형이 다를 경우이다. 이 경우 결과값의 데이터형이 어떤 것이 되느냐가 문제가 될 수도 있다. 먼저, 같은 형끼리의 연산은 결과값도 바로 그 데이터형이 된다.


5/4 // 1 (정수/정수 ➜ 정수)
3/2 // 1 (정수/정수 ➜ 정수)
5.0/4.0 // 1.25 (실수/실수 ➜ 실수)
3.0/2.0 // 1.5 (실수/실수 ➜ 실수)

위 예에서 보듯이 정수형끼리의 나눗셈의 결과도 정수형이 됨에 유의해야한다. 즉, 2/2 는 1.5가 아니라 1이 된다.


 그리고 정수형과 실수형 간 사칙연산 결과는 실수형이 된다는 사실에 유의해야 한다. 즉, 피연산자 중에 하나라도 실수형이라면 결과값도 실수형이 된다.


5.0/4 ➜ 1.25 (실수/정수 ➜ 실수)
2/4.0 ➜ 0.5 (정수/실수 ➜ 실수)

다음 예제에서 이를 확인해 보자


ex03-04.c
#include <stdio.h>
int main()
{
  int ia = 10, ib = 4;
  float fa, fb = 4.0f, fc;
  fa = ia/ib; // (1)
  fc = ia/fb; // (2)
  ib = ia/fb; // (3)
  printf("fa=%f, fc=%f, ib=%d\n", fa, fc, ib);
}

실행 결과

fa=2.000000, fc=2.500000, ib=2

위의 실행 결과에서 변수 fa와 fc값이 왜 다른지 잘 이해해야 한다. (1)에서는 정수/정수이므로 결과값이 먼저 정수형으로 산출된다. 이 값이 실수형으로 형변환되어 실수형 변수 fa에 저장되는 것이다. 그러나 (2)에서는 정수/실수 이므로 결과값이 실수형으로 산출된다. 따라서 정확하게 계산된 값이 실수형 변수 fc에 대입되는 것이다. (3)의 경우는 계산 결과는 실수인데 정수형 변수 ib에 그것을 대입하도록 하였다. 이경우 실수는 정수로 자료형이 변환되며 소수점 이하는 버려진다. 그래서 2.5에서 소수점 이하는 버려진 2 라는 정수값이 ib에 대입되는 것이다.

3.3.1 자동 형변환 (automatic conversion)

 자동 형변환은 이와 같이 산술 연산에서 두 피연산자의 형이 다를 경우 둘 중 더 넓은 자료형으로 다른 하나가 자동으로 변환되는 것을 말한다. 다음에서 오른쪽으로 갈수록 더 넓은 자료형이다.


char < short < int < long < long long < float < double < long double

예를 들어 만약 a + b 에서 a가 long형, b가 double 형이라면 a가 더 넓은 double형으로 자동으로 변환 된 후 덧셈이 수행된다. char형과 long형이라면 둘 다 long형이 된다. 그리고 계산 결과는 항상 넓은 자료형이 된다. 만약 하나는 unsigned 형이고 다른 하나는 signed형이라면 결과를 예측할 수 없으므로 이런 경우는 가급적 피하여야 한다.

3.3.2 명시적인 형변환 (casting)

 사용자가 자료를 명시적으로 형변환해야 할 경우도 있다. 예를 들어서 int형 ia를 long형으로 바꾸고 싶다면 다음과 같이 변수 앞에 (자료형)을 붙여주면 된다.


(long)ia

변수 ia 자체는 변하지 않지만 (long)ia 는 long형 자료가 된다.


int ia=2, ib=4;
float fa = ia/ib;
float fb = (float)ia/ib;

이 예에서 fa 는 0.0 이 fb에는 0.5 가 저장된다. 왜냐면 ia/ib는 둘다 정수이기 때문에 결과값도 정수가 된다. 따라서 소수점 이하가 버려진다. 하지만 (float)ia/ib는 하나는 float형이고 다른 하나는 int 형이므로 ib가 float형으로 자동 형변환 되고 결과값도 float형이 된다. 따라서 정확한 실수값인 0.5가 저장되는 것이다.


 명시적 형변환의 다른 예를 들면 다음과 같다.


(long)(‘a’+2.0f)
fa = (float)((int)ia +1)
da = (double)sa/5

명시적 형변환의 우선 순위는 산술 연산보다 높다는 것도 알아두자.


'프로그래밍언어.Lib > C,C++' 카테고리의 다른 글

3.4 관계 연산자  (0) 2015.05.19
3.2 산술 연산자와 부호 연산자  (0) 2015.05.19
3.3 형변환  (0) 2015.05.19
C/C++의 연산자 종류  (0) 2015.05.19
C/C++의 goto 명령  (0) 2015.05.19
C/C++의 continue 명령  (0) 2015.05.19
Posted by 살레시오

댓글을 달아 주세요

산술 연산자로 다음과 같은 것들이 있다.


연산자

기능

용례

+

덧셈


-

뺄셈


*

곱셈


/

나눗셈

결과는 실수형이다. (2.x에서는 int / int의 결과는 int)

//

자리내림 나눗셈

피연산자가 모두 정수인 경우 나눗셈의 결과 소수점 아래는 버리고 정수만 취한다.

둘 중 하나라도 실수라면 / 연산자와 동일함.

**

거듭제곱

2**10, (1+2j)**20

%

나머지

3%4, -10%3, 12.345%0.4


  나눗셈의 경우 ver 2.x에서는 정수형끼리의 나눗셈은 결과도 정수형이 된다. 다음 결과를 확인해 보라.


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

>>> 4/5

>>> a, b=11,5 #a에 11, b에 5를 대입한다.

>>> b/a

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


하지만 3.x버전에서는 나눗셈의 결과는 무조건 실수로 된다.


■ 2.x버전에서는 정수간 나눗셈의 결과는 정수였다. 즉 1/2는 0, 2/3은 1이다. 하지만 3.x버전에서는 정수간 나눗셈의 결과는 나누어 떨어지는 경우라도 무조건 실수형이 된다. 즉, 1/2는 0.2, 6/3은 2.0이 된다.


  연산자 //는 두 피연산자가 모두 정수일 경우 결과값이 실수이면 소수점 아래는 버린다.


······································································································································

>>> 9//2 # 결과는 4 (정수)

>>> 9//2.0 # 결과는 4.5(실수)

······································································································································


  연산자 %는 나눗셈 수행 후 정수몫을 구하고 난 나머지를 구하는 연산자이다. 다음을 확인해보라.


······································································································································

>>> 3%2

>>> 11.5 % 0.2

······································································································································


연산자 **는 거듭제곱 연산자이다. 다음 연산의 결과값들을 예상해 보자.


······································································································································

>>> 2**10

>>> a, c = 3, 4+5j #변수 a와 c를 차례로 초기화시킨다.

>>> c**a

······································································································································


  복소수의 거듭제곱도 (4+5j)*(4+5j)*(4+5j) 의 결과값을 보여준다. 파이썬에서는 복소수에 대한 산술 연산도 기본적으로 지원하므로 쉽게 수행할 수 있음을 알 수 있다.

#00003


Posted by 살레시오

댓글을 달아 주세요