-> +,- : 더하기, 빼기
-> ++, -- : 값에 1을 더하거나 빼는 연산자
-> 단독으로 쓰일 때는 증감 연산이 그대로 일어나지만, 다른 연산식과 함께 사용 될때에는 연산자의 위치에 따라 차이가 난다
-> 현재 위치에서 증감 연산이 이루어지는 연산자 (선 계산, 후 대입)
++x : x 값에 1을 더하고 대입
--x : x 값에 1을 빼고 대입
-> 대입을 먼저 한 후 계산이 일어남 (선 대입, 후 계산)
x++ : x값에 값을 대입하고 1을 더함
x-- : x값에 값을 대입하고 1을 뺌
package ch03.sec01;
public class IncDec {
public static void main(String[] args) {
int x = 20;
int y = 10;
int z;
x++; // x에 1더함 21
++x; // x에 1더함 22
System.out.println("x=" + x);
y--; // 9
--y; // 8
System.out.println("y=" + y);
z = x++; // x가 z에 먼저 대입이 되므로 z = 22, x = 23
System.out.println("z=" + z);
System.out.println("x=" + x);
z = ++x; // x에 1을 먼저 더하고 z에 대입 z = 24, x=24
System.out.println("z=" + z);
System.out.println("x=" + x);
z = ++x + y++;
//x는 먼저 1을 더하고 대입, y는 z를 위한 연산 먼저 처리 후 1을 더함 x=25, y=9, z=33
System.out.println("z=" + z);
System.out.println("x=" + x);
System.out.println("y=" + y);
}
}
-> +, -, *, /, % : 더하기, 빼기, 곱하기, 나누기, 나머지 구하기
-> %는 나머지 구하는 공식
ex)
6 / 4 = 1 ... 2 일때
6 % 4 = 나머지 값인 2
package ch03.sec02;
public class ArithmeticExam {
public static void main(String[] args) {
byte v1 = 15;
byte v2 = 6;
int v3 = 5;
long v4 = 50l;
int result1 = v1 + v2;
//피연산자는 모두 int 형태로 변환됨
System.out.println(result1);
long result2 = v1 + v2 - v4;
//long 연산자가 포함된 경우 long 타입의 형태로 변환됨
System.out.println(result2);
double result3 = (double) v1/v2;
// 실수의 형태로 값을 내기 위해서는 double로 강제 형변환이 필요
System.out.println(result3);
int result4 = v1 % v2;
// 나머지 연산 구하는 식, 나머지는 정수 형태이기 때문에 int 타입의 형태
System.out.println(result4);
}
}
-> 타입의 허용되는 최대값을 벗어나 타입의 최소값으로 돌아오는 것
ex)
byte의 허용 범위는 -128~127 까지인데
127에서 1을 더하면 128이 나와야 하지만 byte의 허용 범위를 벗어남
그래서 128이 아닌 최소값인 -128로 값이 되돌아와서 출력됨
-> 타입의 허용되는 최소값을 벗어나 타입의 최대값으로 되돌아오는 것
ex)
byte의 허용 범위는 -128~127 까지인데
-128에서 1을 빼면 -129가 나와야 하지만 byte의 허용 범위를 벗어남
그래서 -129가 아닌 최대값 127이 출력됨
package ch03.sec03;
public class OverUnderFlow {
public static void main(String[] args) {
byte var1 = 125;
for(int i=0;i<5;i++) { // 5번 실행
var1++;
//byte 타입의 최대값이 127이기 때문에 값이 넘어가면 최소값인 -128로 되돌아오고 거기서 더해짐
System.out.println(var1);
}
byte var2 = -125;
for(int i=0;i<5;i++) { //5번 실행
var2--;
// byte 타입의 최소값이 -128이기 때문에 값이 넘어가면 최대값인 127로 되돌아오고 1씩 줄어듦
System.out.println(var2);
}
}
}
-> 정수가 연산 속도나 정밀도가 실수에 비해 훨씬 높음!
-> 실수의 경우 정밀도가 떨어지기 때문에 오차가 발생하여 값이 정확하게 떨어져서 나오지 않을 가능성이 있음
package ch03.sec04;
public class Accuracy1 {
public static void main(String[] args) {
int apple = 1; // 사과 1개
double pieceUnit = 0.1; // 사과 한개를 10조각으로 나눔
int number = 7; // 7조각
double result = apple - pieceUnit*number; // 남은 사과 조각 계산
System.out.println(result);
// 결과 값 = 0.29999999993
// 실수의 특성상 오차범위가 있기 때문에 실수간의 계산은 값이 정확하게 떨어지지 않을 수 있음
}
}
-> 위 코드는 원래대로라면 결과값이 0.3이 나와야 하지만 실수 특성상 오차가 발생하기 때문에 값이 정상적으로 나오지 않음
package ch03.sec04;
public class Accuary2{
public static void main(String[] args) {
// TODO Auto-generated method stub
int apple = 1;
int totalpieces = 10; // 사과 조각의 총 개수를 줌
int number = 7;
int result = totalpieces - number;
// 총 사과 조각 - 먹은 조각 = 남은 조각 -> 정수연산으로 계산
System.out.println(result);
System.out.println(result/10.0);
// 결과값 = 0.3
// 정수연산으로 계산했기 때문에 값이 맞아 떨어짐
}
}
-> 결과 값을 확실하게 도출하기 위해서는 위의 코드처럼 정수 끼리 계산 후에 정수와 실수의 연산으로 값을 도출하면 값이 정확하게 나옴
-> Double.isInfinite(x) : x의 값이 무한인지 확인하는 함수
-> Double.isNaN(x) : x의 값이 숫자인지 확인하는 함수
package ch03.sec05;
public class InfinityNaN{
public static void main(String[] args) {
// TODO Auto-generated method stub
int x = 6;
double y = 0.0; // 정수 0으로 나누거나 나머지 값을 구하면 에러가 뜸
double z = x / y;
if(Double.isInfinite(z) | Double.isNaN(z)) { //Double.isInfinite() : 무한대수인지 확인하는 구문, isNaN() : 숫자가 맞는지 확인하는 구문
System.out.println("값 산출 불가");
}
else {
System.out.println(z+2);
}
}
}
-> 피연산자를 비교하는 연산자로 주로 조건문(if)이나 반복문 (for, while)의 동작을 제어할 때 사용됨
실수의 비교 연산자
-> 실수의 경우 오차 범위가 존재하기 때문에 ==으로 비교하면 안 됨
-> 두 실수간 차를 구하고 그 값에 대한 범위를 구하기
ex) -0.0000000001 < x(두 실수간의 차) && < x < 0.0000000001
-> 더 정확하게 Math.abs()라는 함수를 이용하여 두 실수의 차의 절대값을 구하는 방법도 있음
ex) Math.abs(x(두 실수간의 차)) < 0.000000001
package ch03.sec06;
public class CompareExam {
public static void main(String[] args) {
// TODO Auto-generated method stub
int num1 = 10;
int num2 = 10;
boolean result1 = (num1 == num2);
// true : num1과 num2가 맞는지
boolean result2 = (num1 != num2);
// false : num1과 num2가 다른지
boolean result3 = (num1 <= num2);
// true : num1보다 num2가 작거나 같은지
System.out.println(result1);
System.out.println(result2);
System.out.println(result3);
char char1 = 'A';
char char2 = 'B';
boolean result4 = (char1 < char2);
// true : char1이 char2보다 작은지 (ASCII 코드 값으로 계산됨)
System.out.println(result4);
int num3 = 1;
double num4 = 1.0;
boolean result5 = (num3 == num4);
// true : num3과 num4가 같은지
System.out.println(result5);
float num5 = 0.1f;
double num6 = 0.1;
boolean result6 = (num5 == num6);
// false : float의 경우 정밀도가 떨어져서 오차범위가 있으므로 정확한 값을 산출하지 못하기에 같지 않음
boolean result7 = (num5 == (float)num6);
// true : num6을 float 형태로 바꾸면서 값이 같아짐
System.out.println(result6);
System.out.println(result7);
String str1 = "자바";
String str2 = "Java";
boolean result8 = (str1.equals(str2));
// str1의 문자열이 str2와 같은지 확인해보는 것 : equlas()는 문자열 비교에 사용됨
boolean result9 = (!str1.equals(str2));
// str1의 문자열이 str2와 다른지
System.out.println(result8); // false
System.out.println(result9); // true
}
}
-> 두 개 이상의 연산자의 결과를 확인하기 위해 수행하는 연산자
-> 피연산자가 모두 true일 때 결과값이 true
-> 비교와 연산 작업을 모두 수행
-> 피연산자 a와 b가 있을 때 a의 결과 값이 false여도 연산을 계속 진행함
-> 결과값을 직접 받아서 비교 연산을 수행할 때 사용하는 것이 좋음
-> 비교 작업만 수행
-> 피연산자 a와 b가 있을 때 a의 결과값이 false이면 그대로 실행 종료
-> 실행 자체에는 &&를 사용하는 것이 유리하나 결과값을 직접 받아서 연산을 수행할 경우 동작이 제대로 되지 않을 수도 있음
-> 피연산자중 하나만 true이면 결과값이 true
-> 비교와 연산 작업을 모두 진행
-> 피연산자 a와 b가 있을 때 a의 결과값이 true여도 연산을 계속 수행
-> 결과값을 받아서 비교할 경우 정확한 결과값 도출이 가능
-> 비교만 하는 기능
-> 피연산자 a와 b가 있을 때 a의 결과값이 true이면 실행 종료
-> 실행에는 ||을 사용하는 것이 유리하지만, 결과값을 받아서 비교할 경우 정확한 결과값 도출이 어려울 수 있음
-> 피연산자의 결과 값이 서로 다르면 true
-> 피연산자의 결과를 반대로 표출함
ex) true > false, false > true
package ch03.sec07;
public class LogicalExam {
public static void main(String[] args) {
int charCode = 'A';
if ((charCode >= 'A') & (charCode <= 'Z')) {
// & : 두개의 연산자가 모두 true일 경우 true 출력
System.out.println("대문자");
}
if ((charCode >= 'a') & (charCode <= 'z')) {
System.out.println("소문자");
}
if ((charCode >= '0') & (charCode <= '9')) {
System.out.println("숫자");
}
int value = 7;
if((value%2 == 0) | (value%3 == 0)) {
// | : 두개의 연산자 중에 하나만 true일 경우 true 출력
System.out.println("2 또는 3의 배수이군요");
}
boolean result = (value%2 == 0) || (value%3 == 0);
if(!result) {
// ! : 결과 값의 반대로 출력
System.out.println("2 또는 3의 배수가 아님");
}
}
}
-> bit 단위로 논리 연산을 수행함 (2진수 연산)
-> 피연산자는 0과 1
-> byte, short, int, long만 사용 가능함
-> 최상위 비트가 0이면 양수, 1이면 음수
ex)
양수 = 0000 0000
음수 = 1000 0000
-> AND(&), OR(|), XOR(^), NOT(~) 연산자가 있음 : 원리는 위에 설명한 것과 동일
package ch03.sec08;
public class BitLogic{
public static void main(String[] args) {
int a = 40;
int b = 18;
System.out.println(a&b);
// 40&18 = 0010 1000 & 0001 0010 => 0000 0000 : 0 (두 bit의 값이 모두 1일 경우에만 1 출력)
System.out.println(a|b);
// 40|18 = 0010 1000 | 0001 0010 => 0011 1010 : 58 (두 bit의 값 중에 하나라도 1이 있으면 1 출력)
System.out.println(a^b);
// 40^18 = 0010 1000 ^ 0001 0010 => 0011 1010 : 58 (두 bit의 값이 서로 다르면 1출력)
System.out.println(~a);
// ~40 = ~0010 1000 => 1101 0111 : -41 (0과 1의 값이 반대로 됨)
byte receiveData = -98;
int unsignedInt1 = receiveData & 255;
// byte 값의 데이터와 int 정수의 값을 and 연산자를 통해 정수값을 받고 int 값으로 변환
System.out.println(unsignedInt1);
// 1001 1110 & 1111 1111 = 1001 1110 = 158
int unsignedInt2 = Byte.toUnsignedInt(receiveData);
// Byte.toUnsingedInt : byte 값을 int 값으로 변환해주는 함수
System.out.println(unsignedInt2); // 158
int test = 158;
byte btest = (byte) test;
//int 타입의 값을 byte값으로 강제 형변환 하는 것
System.out.println(btest); // -98
}
}
-> 정수 a의 각 bit를 b만큼 왼쪽으로 이동
-> 오른쪽 빈자리는 0으로 채움
-> a x 2^b와 결과값이 동일
ex)
5 << 3 : 00000101 << 3비트씩 왼쪽으로 이동 = 00101000 : 40
-> 정수 a의 각 bit를 b만큼 오른쪽으로 이동
-> 왼쪽 빈자리는 최상위 부호 bit와 같은 값으로 채움 (양수는 0, 음수는 1)
-> a / 2^b와 결과값이 동일
ex)
13 >> 2 : 00001101 >> 2비트씩 오른쪽으로 이동 (빈자리는 0으로 채움)
-13 >> 2 : 11110011 >> 2비트씩 오른쪽으로 이동 (빈자리는 1로 채움)
-> 정수 a의 각 비트를 b만큼 오른쪽으로 이동
-> 왼쪽의 빈자리는 0으로 채움 (a<<b의 반대 개념)
ex)
13 >>> 2 : 00001101 >>> 2비트씩 오른쪽으로 이동 = 00000011 : 3
-13 >>> 2 : 11110011 >>> 2비트씩 오른쪽으로 이동 = 00111100 : 60 (byte 연산자일 때 한정)
package ch03.sec09;
public class BitShift {
public static void main(String[] args) {
int num1 = 1;
int result1 = num1 << 4; // num1의 bit를 왼쪽으로 4칸 이동 후 빈공간을 0으로 채움
int result2 = num1 * (int)Math.pow(2, 4); // 2의 4승을 계산 후 double값으로 출력하기에 정수로 출력하려면 int 타입의 형태로 변환해야함
System.out.println(result1); // 16
System.out.println(result2); // 16
int num2 = -16;
int result3 = num2 >> 3; // num2의 bit를 오른쪽으로 3칸 이동 후 빈공간을 최상위 비트 숫자로 채움 (양수:0, 음수:1)
int result4 = num2 / (int)Math.pow(2, 3); // num2의 값을 2의 3승으로 나눔
System.out.println(result3); //-2
System.out.println(result4); //-2
}
}
-> 우측 피연산자의 값을 좌측 피연산자에 대입하고 우측 피연산자와의 연산을 수행함
-> 우측 피연산자가 연산식일 경우 우측 피연산자의 연산식을 수행 후 좌측 피연산자에 대입 후 연산 시행!
package ch03.sec10;
public class AssignmentExam {
public static void main(String[] args) {
int result = 0; //result라는 초기값을 설정해야함
result += 10; // result = result + 10
System.out.println(result); // 10
result -= 5; // result = result - 5
System.out.println(result); // 5
result *= 3; // result = result * 3
System.out.println(result); // 15
result /= 3; // result = result / 3
System.out.println(result); // 5
result %= 3; // result = result % 3 (3으로 나눴을 때 나머지 구하기)
System.out.println(result); // 2
}
}
-> 3개의 피연산자를 가짐
-> 구조:
조건식(피연산자1) ? 값/연산식(피연산자2) : 값/연산식(피연산자3)
-> 피연산자1은 조건식이므로 boolean 값을 가지게 됨
-> 피연산자1의 결과값이 true이면 피연산자2가 false이면 피연산자3이 출력
package ch03.sec11;
public class exam01 {
public static void main(String[] args) {
int score = 85;
char grade = (score > 90) ? 'A' : (score>80) ? 'B' : (score>70) ? 'C' : 'D'; // 90점이상:A, 80점이상:B, 70점이상:C, 미만:D
// : 3개의 피연산자를 가진다
// : 조건식(피연산자1) ? 값 또는 연산식(피연산자2) : 값 또는 연산식(피연산자3)의 구조
// : 피연산자1의 경우 boolean 변수를 가짐
// : 피연산자1의 결과값이 true이면 피연산자2의 값이, false이면 피연산자3의 값이 출력됨.
System.out.println(grade);
}
}