자바 산술 연산자에 대해 알아보자

2024. 12. 27. 23:43JAVA

728x90
반응형

 

 안녕하세요. 진득코딩입니다.

 

 이번 시간에는 지난 시간에 이어 산술 연산자에 대해 알아보도록 하겠습니다.

 

 산술 연산자는 여러 연산자 중에 프로그래밍에 가장 많이 사용되는 연산자로 중요도가 높습니다.

 

사칙 연산자 + - * /

 

  •  사칙 연산자는 덧셈(+), 뺄셈(-), 곱셈(*), 나눗셈을 의미합니다.

  • 곱셈(*), 나눗셈(/), 나머지(%) 연산자가 덧셈(+), 뺄셈(-) 연산자보다 우선순위가 높으므로 먼저 처리됩니다.

예제 3-5

 

  • 나누기 연산자의 두 피연산자가 모두 int 타입인 경우, 연산 결과 역시 int 타입입니다.

  • 그래서 10을 4로 나눈 결과가 2.5가 아닌 2로 반올림이 발생하지 않습니다.

  • 그래서 올바른 연산결과를 얻기 위해서는 두 피연산자 중 어느 한쪽을 실수형으로 형변환해야 합니다.

  • 피연산자가 정수형인 경우, 나누는 수로 0을 사용할 수 없습니다.

  • 만일 0으로 나누면, 컴파일은 정상적으로 되지만 실행 시 오류(ArithmeticException)가 발생합니다.

  • 부동 소수점값인 0.0f, 0.0d로 나누는 것은 가능하지만 그 결과는 Infinity(무한대)입니다.
x y x / y x % y
유한수 +-0.0 +-infinity NaN
유한수 +-infinity +-0.0 x
+-0.0 +-0.0 NaN NaN
+-infinity 유한수 +-infinity NaN
+-infinity +-infinity NaN NaN

 

  • 위 표는 나눔셈 연산자 '/'와 나머지 연산자 '%'의 피연산자가 무한대(Infinity) 또는 0.0인 경우의 결과를 표로 정리한 것입니다.
  • NaN은 'Not a Number'를 줄인 것으로, 숫자가 아니라는 뜻입니다.

예제 3-6

 

  • a와 b는 모두 int형보다 작은 byte형이기 때문에 연산자 '+'는 이 두 개의 피연산자들의 자료형을 int형으로 변환한 다음 연산(덧셈)을 수행합니다.

  • 그래서 'a + b'의 연산 결과는 byte형이 아닌 int형(4 byte)입니다.

  • 4 byte의 값을 1byte의 변수에 형변환 없이 저장하려고 했기 때문에 에러가 발생합니다.

  • 큰 자료형의 값을 작은 자료형의 변수에 저장하려면 명시적으로 형변환 연산자를 사용해서 변환해주어야 합니다.

  • 'byte c = a + b;'를 '(byte)(a + b);'와 같이 변경해야 컴파일 에러가 발생하지 않습니다.

예제 3-7

 

  • 10 * 30의 결과는 300이지만 위 예제를 실행하면 44가 출력됩니다.

  • 이는 큰 자료형에서 작은 자료형으로 변환하면서 데이터의 손실이 발생한 것입니다.

  • 이러한 값 손실을 예방하기 위해서는 충분히 큰 자료형을 사용해야 합니다.

예제 3-8

 

  • 위 예제는 '2000000000000'이 나와야 하지만 전혀 다른 값이 출력되었습니다.

  • 그 이유는 int타입과 int타입의 연산결과는 int타입이기 때문입니다.

  • 'a * b'의 결과가 이미 int타입의 값(-1454759936)이므로 long형으로 자동 형변환 되어도 값은 변하지 않습니다.

  • 올바른 결과를 얻으려면 변수 a 또는 b의 타입을 'long'으로 형변환해야 합니다.

예제 3-9

 

  • a의 값이 예상과 다른 결과가 출력된 이유는 int타입과 int타입의 연산결과는 int타입인데, 연산결과가 int타입의 최댓값인 약 2*10^9을 넘으므로 오버플로우(overflow)가 발생했기 때문입니다.

  • 이미 오버플로우가 발생한 값을 long타입의 변수에 저장해도 올바르지 않은 값이 들어가게 됩니다.

예제 3-10

 

  • 먼저 곱하게 되면 곱한 결과 값이 int의 범위를 넘어서기 때문에 예상과 다른 결과가 나오게 됩니다.

  • 이처럼 같은 의미의 식이라도 연산의 순서에 따라 다른 결과가 나올 수 있습니다.

예제 3-11

 

  • 사칙연산의 피연산자로 숫자뿐만 아니라 문자도 가능합니다.
  • 문자는 실제로 해당 문자의 유니코드(부호없는 정수)로 바뀌어 저장되므로 문자 간의 사칙연산은 정수 간의 연산과 동일합니다.

  • 주로 뺄셈을 하는 경우가 대부분이며, 문자 '2'를 숫자로 변환하려면 문자 '0'을 빼주면 됩니다.

  • 이는 유니코드 '0' ~ '9'까지의 문자가 연속적으로 배치되어 있기 때문입니다.

  • 'A' ~ 'Z'와 'a' ~ 'z'도 연선적으로 배치되어 있기 때문에 문자 'd'에서 문자 'a'를 빼면 3이 나오게 됩니다.

예제 3-12

 

  • 'c1 + 1'을 계산할 때, c1이 char형이므로 int형으로 변환한 후 덧셈연산을 수행하게 됩니다.

  • 따라서 'c1 + 1'은 '97 + 1'이 되고 결과적으로 int형 변수 i에는 98이 저장됩니다.

  • 'c2++'은 형변환 없이 c2에 저장되어 있는 값을 1 증가시키므로, 원래 저장되어 있던 값인 97이 1씩 두 번 증가되어 99가 됩니다.

  • 코드값이 10진수로 99인 문자는 'c'이기 때문에 c2를 출력하면, 'c'가 화면에 출력됩니다.

  • 'c2++' 대신에 c2 = c2 + 1을 사용하면 에러가 발생하는데 c2 + 1의 연산결과는 int형이며, 그 결과를 다시 c2에 담으려면 형변환 연산자를 이용하여 char형으로 형변환해야 하기 때문입니다.

예제 3-13

 

  • 'a + 1'이 리터럴 간의 연산이기 때문에 형변환을 하지 않아도 에러가 발생하지 않았습니다.

  • 상수 또는 리터럴 간의 연산은 실행과정 동안 변하는 값이 아니기 때문에, 컴파일 시에 컴파일러가 계산해서 그 결과로 대체함으로써 코드를 보다 효율적으로 만듭니다.

예제 3-14

  • 소문자 a부터 z까지, 그리고 대문자 A부터 Z까지, 숫자 0부터 9까지 연속적으로 코드가 지정되어 있기 때문에 위와 같은 결과가 나오게 되었습니다.

  • 위에 나온 결과를 바탕으로 대문자를 소문자로, 소문자를 대문자로 변환하는 프로그램을 작성할 수 있습니다.

  • 대문자와 소문자 간의 코드값 차이는 10진수로 32입니다.

예제 3-15

 

  • 소문자를 대문자로 변경하려면, 소문자 a의 코드값에서 32를 빼면 되고, 대문자를 소문자로 변환하려면 대문자 코드값에 32를 더해주면 됩니다.

  • char형과 int형 간의 뺄셈연산 결과는 int형이므로, 연산 후 char형으로 다시 형변환해야 합니다.

예제 3-16

 

  • int형 간의 나눗셈 'int/int'를 수행하면 결과가 float나 double이 아닌 int입니다.

  • 또한 나눗셈의 결과를 반올림하지 않고 버린 결과가 나오게 됩니다.

  • 나눗셈 연산자의 이러한 성질을 이용해서 실수형 변수 pi의 값을 소수점 셋째 자리까지만 빼낼 수 있습니다.

예제 3-17

 

  • 만일 버리지 않고 반올림을 하고 싶으면 위와 같이 0.5를 더해주면 됩니다.

  • 0.5를 더했을 때 반올림해야 할 상황에서는 1이 올라가고, 그렇지 않은 상황에서는 어차피 해당 수는 버려지기 때문에 반올림을 할 수 있게 됩니다.

예제 3-18

 

  • 위와 같이 Math.round()를 사용하면 좀 더 간단히 반올림할 수 있습니다.

  • round메서드는 매개변수로 받은 값을 소수점 첫째 자리에서 반올림하고 그 결과를 정수로 돌려주는 메서드입니다.

나머지 연산자 %

 

  • 나머지 연산자는 왼쪽의 피연산자를 오른쪽 피연산자로 나누고 난 나머지 값을 결과로 반환하는 연산자입니다.

  • 나눗셈에서처럼 나누는 수 (오른쪽 피연산자)로 0을 사용할 수 없습니다.

  • 나머지 연산자는 주로 짝수, 홀수 또는 배수 검사 등에 주로 사용됩니다.

예제 3-19

 

  • 나눗셈 연산자와 나머지 연산자를 이용해서 몫과 나머지를 구하는 예제입니다.

  • 간단한 예제이기 때문에 큰 어려움 없이 이해 가능한 예제라고 생각합니다.

예제 3-20

 

  • 나머지 연산자(%)는 나누는 수로 음수도 허용합니다.

  • 그러나 부호는 무시되므로 결과는 음수의 절댓값으로 나눈 나머지와 결과가 같습니다.

  • 간단하게 생각해서 피연산자의 부호를 모두 무시하고, 나머지 연산을 한 결과에 왼쪽 피연산자(나눠지는 수)의 부호를 붙이면 됩니다.


 

 이번 포스팅은 앞선 포스팅들에 비해 예제가 많은 포스팅이었습니다.

 이렇게 많은 예제가 나온다는 것은 선수 학습한 내용들이 많기 때문에 써먹을 수 있는 지식들이 많이 쌓인 것이라고 생각합니다.

 

 코드도 따라 치면서 계속해서 이클립스와 친해지는 시간을 가지면 좋을 것 같습니다.

 이번 포스팅은 여기까지입니다.

 포스팅을 보시면서 궁금하시거나 의문인 부분들은 언제든지 댓글로 남겨주시면 성심성의껏 답글 달아드리겠습니다.

 끝까지 봐주셔서 감사합니다.😊

728x90
반응형
LIST