본문 바로가기

별걸다하는 IT/프로그래밍언어

[Java, C, C++ 기초 강좌] 산술연산자 그리고 형변환 ( + 모듈연산, 0으로 나누기)

[ C, C++ 완전정리 목차 ]

안녕하세요~~! 오늘도 방문해주신 여러분들 감사합니다. ~ :)

저번 연산자 포스팅에서 연산자를 전반적으로 훑어봤는데요~!

이번에는 하나하나 들어가보려고 합니다. 오늘은 산술연산자부터 살펴볼거예요~

저번에 이 연산자는 이항연산자라고 했던거 기억하고 오기~~

 

저번 포스팅이 궁금하신 분들은~ 요기 ↓

시작해보까요~!?

 

[Java, C, C++ 강좌] 연산자란? 연산자 종류 - 단항 연산자, 이항연산자, 삼항연산자

[C, C++, 프로그래밍 기초 완전 정복 목차] [ 연산자 Operator ] 안녕하세요~!! 오늘은 연산자에 대해서 배워볼까 합니당 ㅎㅎ 서론.. 들어가기 전 컴퓨터는 원래 계산기였어요 ㅎㅎ 지금이야 뭐 워낙 빠르게 발..

jhnyang.tistory.com

산술연산자

산술연산자는 처음 프로그래밍을 배우는 친구들도 별로 어려워하지 않는 부문 중 하나이기도 해요~!

왜냐면 우리는 초등학교때부터 사칙연산을 수도 없이 해와서 이미 내공이 단단히 단련되어 있기 때문이죠 ㅎㅎㅎ

 

연산자

연산자의 종류 

연산자 기능

결합방향

+

산술연산자

두 피연산자를 더하기

-

산술연산자

두 피연산자를 빼요

*

산술연산자

곱하기 

/

산술연산자

나누기

%

산술연산자

나머지 구하기

참고로 산술연산자에서 보이는 '*'는 곱하기 '×' 와 같습니다.

그리고 '/'는 나누기 '÷' 예요 ㅎㅎ

산술연산자 실습

코드로 바로 확인해볼까요?

### C언어
#include <stdio.h>
int main() {
    int num1 = 4, num2 = 3;
    printf("%d + %d = %d \n", num1, num2, num1+num2);
    printf("%d - %d = %d \n", num1, num2, num1-num2);
    printf("%d * %d = %d \n", num1, num2, num1*num2);
    printf("%d / %d = %d \n", num1, num2, num1/num2);
    printf("%d %% %d = %d \n", num1, num2, num1%num2);
    return 0;
}
### C++ 언어
#include <iostream>
using namespace std;
int main() {
    int num1=4, num2 =3;
    cout<<num1<<" + "<<num2<<" = "<<num1+num2<<endl;
    cout<<num1<<" - "<<num2<<" = "<<num1-num2<<endl;
    cout<<num1<<" * "<<num2<<" = "<<num1*num2<<endl;
    cout<<num1<<" / "<<num2<<" = "<<num1/num2<<endl;
    cout<<num1<<" % "<<num2<<" = "<<num1%num2<<endl;
    return 0;
}
### Java 언어 
class Main {
	public static void main (String[] args) throws java.lang.Exception {
	    int num1=4, num2=3;
		System.out.println(num1+" + "+num2+" = "+(num1+num2)); //요렇게 해도 되고
        System.out.printf("%d - %d = %d\n", num1, num2, num1-num2); //C언어 출력과 유사
        ...똑같이 반복
	}
}

결과창

산술 변환 (usual arithmetic conversion)

4 / 3 = 1

Q: 어라? 결과창에 4번째 줄 보면 4 나누기 3은 1.333...이 되어야 하는데 1이 나오네요?! 연산 수행이 제대로 안됐어요 왜그런가요?

A: 정수의 승격 기억나시나요? 형변환 포스팅 때 하단쯤에서 다뤘었어요 ㅎㅎ 다시 보려면 아래 포스팅으로 ~

 

간단하게 다시 복습해보자면, int형 이하의 자료형 한에서는 산술연산시 int로 변환되서 수행되기 때문에 연산결과가 int가 된다는 것이었습니당~

num1도 int이고 num2도 int이기 때문에 num1/num2 또한 정수형으로 반환이 돼요

조심해야 할 건, 데이터 손실이 일어난 것이기 때문에 반올림 된 값이 반환되는 것이 아니라, 소수점 이하는 버려지고 정수부문만 반환됩니다.

 

Q: 그럼 이렇게 잘린 값 말고 소수점까지 나오는 제대로 된 값을 받으려면 우뜨케 해야 하나요?

A: 두 피연산자 중 하나를 실수로 바꾸거나 둘 다 실수로 바꾸거나~!

 

Q: int이하의 피연산들끼리는 어떻게 지지고 볶든 int로 반환된다고 하면, int 이상의 자료형에서는 어떻게 수행이 되는지 궁금합니다

물론, 같은 데이터 타입의 경우면, 그 데이터 타입으로 결과가 반환되겠죠?ㅎㅎ float 나누기 float 은 float일거예요 ㅎㅎ

그런데 float 나누기 int 라던가,, int 나누기 double이라던가.. 두 피연산자의 자료형이 다를 경우에는 큰 값에 맞춰집니다. 반환값도 그래서 큰 값으로 돼요 ㅎㅎ 요것도 컴파일러가 해주는 묵시적 형변환 중 하나입니다.

이렇게 타입이 다른 두 피연산자가 사칙연산을 수행할 경우, 오버플로우가 발생할 가능성이 높기 때문에, 이를 최소화하고자 컴파일러가 자동으로 큰쪽에 맞춰주는거예요ㅎㅎ

요렇게~

코드로 확인해보기~! 

 int num1=4; float num2 = 3f;
 System.out.println(num1+" / "+num2+" = "+(num1 / num2)); 

↑ 자바 결과: 4 / 3.0 = 1.3333334

float num1=4; int num2 = 3;
System.out.println(num1+" / "+num2+" = "+(num1 / num2)); 

↑ 자바 결과: 4.0 / 3 = 1.3333334

 float num1= 4; int num2 =3;
 cout<<num1<<" / "<<num2<<" = "<<num1/num2<<endl;

↑ C++ 결과: 4 / 3 = 1.3333334

 

근데 똑같은 정수 타입의 수인데,, 이 나눗셈 때문에 하나의 타입만 변경하는게 뭔가 넌센스예요 그쵸?

그럴 경우에는 그냥 명시적 형변환을 사용해서 타입을 맞춰줘도 됩니다 ㅎㅎ

 int num1= 4; int num2 =3;
 cout<<num1<<" / "<<num2<<" = "<<(float)num1/num2<<endl;

 

간단하게, 정수끼리 나눗셈 연산을 진행할 때는, 나눗셈의 을 구한다고 생각하면 쉽고 ~~

피연산자의 데이터 타입으로 변경을 하던 명시적 형변환으로 변경을 하던, 실수로 변환을 하나라도 해줄경우, 실제 나누기를 수행한다 생각하면 됩니다.

% 모듈연산자

산술 연산자는 다 아는 것 같은데 '%'이 연산자만 좀 생소하죠?

'%'는 모듈이라고 부르는데, 나머지를 반환하는 역할을 합니다.

--C++
#include <iostream>
using namespace std;
int main() {
   int apple = 100; //총 사과 개수
   int apple_per_person = 7; // 한 사람이 가져갈 사과 개수 
   cout<<apple % apple_per_person<<endl; // 사과를 사람들에게 할당해줬을 때 남은 사과
   return 0;
}
-- 자바 
class Main {
	public static void main (String[] args) throws java.lang.Exception {
    	int apple = 100; 
        int applePerPerson = 7; 
        System.out.println(apple % applePerPerson);
	}
}

100 나누기 7은 몫이 14이고 나머지가 2예요. 따라서 결과값은 2가 출력됩니다.

나머지 연산의 특성상 피연산자로 정수만 허용됩니다.

모듈연산은 매우 유용하게 잘 사용되니 꼭 알고 있으세요~ ㅎㅎ

0으로 나누기

나누기를 할 때 0으로 나누면 안됩니다! 이건 수학적으로 정의되어 있어요

수학적으로 0으로 나누기는 성립되지 않는 개념이다. 

코드에서도 마찬가지입니다. 0으로 나누려고 하면 에러를 발생시켜요 ㅎㅎ

제가 이전 포스팅에서 연산자를 단축키라고 비유했던거 기억나시나요??

어떻게 보면 나눗셈도 뺄셈의 단축키예요. 10나누기 2는 10에서 계속 2를 빼면서 몇번뺐을 때 0이 되냐는 거잖아요 ㅎㅎ 근데 만약 10 나누기 0을 했다고 생각해보세요... 만약 나누기가 이와같이 정의되어 있다면, 10에서 줄어들지를 않으니,, 무한루프를 돌겠죠..? 그러다보면 컴퓨터가 뻑날거예요 ㅎㅎ 뭐...결론은, 애초에 0으로 나눈다는건 말이 안된다 라는게 수학의 규칙이다 컴퓨터에서도 똑같이 적용된다~! 입니다.

### 자바
public class Main {
	public static void main(String[] args) {
		System.out.println(9/0);
	}
}

요렇게 ArithmeticException 에러가 뜹니다. 

### C++
#include <iostream>
using namespace std;
int main()
{
	cout << 9 / 0 << endl;
	return 0;
}

근데 0이 실수면 결과가 다르다?

그런데 특이한 점은 만약 나누기를 0으로 하지 않고 실수인 0.0으로 진행하게 되면 에러가 발생하지 않습니다.

#include <iostream>
using namespace std;
int main(){
	float num1 = 4; float num2 = 0.0;
	cout << num1 << " / " << num2 << " = " << num1 / num2 << endl;
	return 0;
}

inf라고 Infinity(무한대)가 발생해요.

 

왜 같은 0인데 이렇게 되느냐...

float이나 double 같은 실수 타입은 현재 IEEE 754라는 표준을 따르고 있습니다. 컴퓨터는 이진수로 데이터를 표현한다는 것을 기억하세요! 이진수로 실수 표현 방법을 정의한게 IEEE 745예요

(논리회로 과목에서 부동소수점 표현 방법에 대해 상세하게 배우게 될거예요,,)

그런데 IEEE 754에서 1.0 / 0.0 을 무한으로, -1.0 / 0.0을 마이너스 무한으로 0.0/0.0을 NaN (Not a Number)로 정의했고 이를 따르기 때문에 이렇게 결과가 나온겁니다.

 

좀 더 자세한 정보를 원하신다면 아래 링크를 참조하세요

위키피디아 - IEEE 745

위키피디아 - Division by zero

스택오버플로우 - Why doesn't Java throw an Exception when dividing by 0.0?

등등.. 사실 검색하면 정보가 많이 나와요 ㅎㅎ

char도 산술 연산이 가능하다?

가능합니다 ㅎㅎ

char도 1바이트 크기를 가지는 공간이고 안에 이진수를 저장하는 상자예요.

1바이트면 8비트고 안에 들은 데이터 값이 '00001000' 이면 10진수로 8을 의미하겠죠?

char 또한 int와 같은 메모리를 할당하는 자료형이기 때문에 정수표현이 가능합니다.

그런데 어떻게 문자를 표현하냐면, 서로 약속을 정해놓은 거예요. 숫자 65를 문자로 표현했을 때 A라고 정하쟈~ !

A가 65고 결국 65도 A이다~! 같은 이진수를 출력을 10진수로 하면 정수를 의미, 문자로 출력하면 해당 수와 약속으로 매핑해놓은 문자를 출력해주자~ 하는거예요 ㅎㅎ 아무튼 char또한 결국 정수이기 때문에 연산이 가능한거랍니당

 

코드로 문자가 가진 정수값 확인해보기 ~!

#include <stdio.h>
int main() {
    char A = 'A';
    printf("%d\n", A); 
    printf("%c\n", A); 
    printf("%d\n", A + 1);
    printf("%c\n", A + 1);
    return 0;
}

 

결과값

나중에 문자 관련된 파트에서 다 자세하게 다뤄지겠지만...매핑에 대해 궁금하신 분들은 '아스키코드, 유니코드'를 검색해보세요 :)

 

참고할만한 알고리즘 연습 문제:

 

[백준 BAEKJOON]1000번 A+B,1001번 A-B 문제 1008번 A/B문제(사칙연산)

백준(BAEKJOON) 알고리즘 문제 풀기- 난이도: 하 이번엔 사칙연산과 관련된 문제들이예요 [1000] A+B ---------------------------------------------------------------------------------------- 문제: 두 정수..

jhnyang.tistory.com

오늘은 여기까지입니다~!

오늘 하루도 고생많았어요 여러분들 ~!

공감, 댓글, 광고보답 항상 감사드립니다. 또 정성스럽게 작성한 포스팅으로 다시 찾아뵐게요