JAVA_#1_2
1일차_2
문자열 결합
문자열 결합 순서에 의한 차이가 있다.
"" + 7 + 7 => "7" + "7"
7+ 7 + "" => 14 + "" => "14"
연산자
증감연산자
class Operator2_1 {
public static void main(String[] args) {
int k = 0, j = 3;
// 후위 형
k = j++;
System.out.println("k = j++;, k = " + k);
System.out.println("k = j++;, j = " + j);
// 다르게 표현 가능
// k = j;
// j++;
// System.out.println("k = j++;, k = " + k);
// System.out.println("k = j++;, j = " + j);
// 현재 k 값이 3, j값이 4인 것을 초기화 시킨다.
// 값 초기화
k = 0;
j = 3;
// 전위 형
k = ++j;
System.out.println("k = ++j;, k = " + k);
System.out.println("k = ++j;, j = " + j);
// 다르게 표현 가능
// ++j;
// k = j;
// System.out.println("k = ++j;, k = " + k);
// System.out.println("k = ++j;, j = " + j);
}
}
형변환 연산자
형변환이란?
- 변수 또는 상수의 타입을 다른 타입으로 변환하는 것을 의미합니다.
- 형식 : (타입)피연산자
자동 형변환 개념
float f = 1234; => int 타입의 값을 float타입의 변수에 저장!
- 상대적으로 int 타입이 float 타입 보다 크기가 작기 때문에 가능합니다.
float f = (float)1234; => 사실 변수와 리터럴의 타입을 일치 시켜줘야 합니다.
- 우리가 보는 코드에는 형변환이 생략되어 있었습니다. 즉, 컴파일러에 의해 자동으로 형변환된 겁니다.
int i = 3.14f;
- 이렇게 큰 타입을 작은 타입에 저장할 때 Error 가 발생합니다.
- 3.14f 가 int 타입으로 변환될 때 소수점이 사라지면서 원래 값이 달라집니다.
- 즉, 값 손실이 발생하는데 이런 경우, 컴파일러가 자동으로 형변환을 안 해줍니다.
int i = (int)3.14f; => 이렇게 직접 수동으로 형변환을 시켜줘야 합니다.
사칙 연산자
class Operator4_1 {
public static void main(String[] args) {
int a = 10, b = 4;
// 덧셈
System.out.print("a + b = ");
System.out.println(a + b);
// 뺄셈
System.out.print("a - b = ");
System.out.println(a - b);
// 곱셈
System.out.print("a * b = ");
System.out.println(a * b);
// 나눗셈
// 소수점 이하는 버려진다.
System.out.print("a / b = ");
System.out.println(a / b);
//(float)의 위치가 a에 붙어도 괜찮다.
// 10 / 4.0f -> 10.0f / 4.0f -> 2.5
System.out.print("a / (float)b = ");
System.out.println(a / (float)b);
}
}
산술변환
class Operator4_2 {
public static void main(String[] args) {
char ch = '2';
// 문자 '2' 는 숫자로 50, '0' 은 48
// 따라서 int 타입으로 자동으로 변하기 때문에 50 - 48 = 2
System.out.print("ch - '0' = ");
System.out.println(ch - '0');
int a = 1_000_000; // 1백만
int b = 2_000_000; // 2백만
// a * b = 2_000_000_000_000 -> 10^12
// long 에 저장하려는 것은 맞지만 a * b 의 결과 타입이 int
// 따라서 이미 계산을 할 때 오버플로우 발생! -> 따라서 계산을 할 때 형변환 필요!
// long l = a * b; // -1454759936
long l = (long)a * b;
// long * int -> long * long => 1_000_000L * 2_000_000 -> 1_000_000L * 2_000_000L
System.out.println("l = " + l);
}
}
연산 전에 피연산자의 타입을 일치시키는 것을 의미합니다.
1. 두 피연산자의 타입을 같게 일치시킨다.(보다 큰 타입으로 일치)
* long + int => long + long = long
* float + int =>float + float = float
* double + float => double + double = double
2. 피연산자의 타입이 int 보다 작은 타입 이면 int 로 변환된다.
* byte + short => int + int = int
* char + short => int + int = int
* 이는 int 보다 작은 타입이 계산을 통해 쉽게 범위가 넘어갈 수 있기 때문에 오버플로우가 발생해
정확한 계산값을 가져오지 못할 수 있어서 미리 큰 범위인 int 타입으로 변환시킨 후 계산하는 것입니다.
int가 default 값이기 때문에
int * int 의 경우 int 최대값이 초과할 수 있다.
이런 경우에는 (long) int값 * int 값; 을 직접 변환시켜야 한다.
Math 클래스
Math는 수학과 관련된 메서드를 가지고 있는 클래스 입니다.
메서드는 '특정한 기능을 수행하기 위해 코드로 작성된 단위!' 라고 생각하시면 됩니다.
round() : 실수를 소수점 첫 째자리에서 반올림한 정수를 반환합니다.
ceil() : 올림값을 double 형으로 반환합니다.
floor() : 내림값을 double 형으로 반환합니다.
abs() : int, double 기본형 모두 사용 가능하며 절대값을 얻습니다.
나머지 연산자 %
오른쪽 피연산자로 나누고 남은 나머지를 반환합니다.
나누는 피연산자는 0이 아닌 정수만 허용합니다.
부호는 무시됩니다.
아래 예제코드
class Operator5_1 {
public static void main(String[] args) {
long result = Math.round(3.645678);
System.out.println("result = " + result);
// 소수점 4째 자리에서 반올림한 값을 구하라!
double pi = 3.141592;
// pi * 1000 = 3141.592
// Math.round(3141.592) = 3142
// 3142 / 1000.0 = 3.142
double shortPi = Math.round(pi * 1000) / 1000.0;
System.out.println(shortPi); // 3.142
// 3.141 구하기!
double pi2 = 3.141592;
// pi2 * 1000 = 3141.592
// (int)3141.592
// int는 소수점 값 X
System.out.println("(int)(pi2 * 1000) = " + (int) (pi2 * 1000));
// int로 소수점 값을 없애고, 3141 값을 얻은 후 3141 / 1000.0을 통해 3.141이라는 문자 값을 얻음
// / 1000.0이 아닌 1000을 하게 되면 int값으로 소수점 이하 삭제
System.out.println("(int)(pi2 * 1000) / 1000.0 = " + (int) (pi2 * 1000) / 1000.0);
}
}
비교연산자
두 피연산자를 비교해서 true(참) 또는 false(거짓)를 반환합니다.
문자열의 비교
문자열 비교에는 == 대신 equals()를 사용해야 합니다.
equals : 비교하고자 하는 두 피연산자의 값 자체를 비교합니다.
== : 비교하고자 하는 두 피연산자의 주소값을 비교합니다.
(메모리 공간은 각각이 구분될 수 있도록 '메모리 주소'를 가지고 있다.) 이 때문에
equals 와 == 값이 일치할 때도, 일치하지 않을 때 있음.
논리 연산자
class Operator7_2 {
public static void main(String[] args) {
int num1 = 8, num2 = -8;
System.out.println("8의 2진수 = " + Integer.toBinaryString(num1)); // 0 생략 가능!
System.out.println("-8의 2진수 = " + Integer.toBinaryString(num2));
System.out.println("-9의 2진수 = " + Integer.toBinaryString(-9)); // 32bit, int = 4byte
// 00000000000000000000000000001000 , 8
// 11111111111111111111111111111000 , -8
System.out.println("& 연산자에 의한 결과 = " + (num1 & num2)); // 00000000000000000000000000001000, 8
System.out.println("| 연산자에 의한 결과 = " + (num1 | num2)); // 11111111111111111111111111111000, -8
System.out.println("^ 연산자에 의한 결과 = " + (num1 ^ num2)); // 11111111111111111111111111110000, -16
System.out.println("~ 연산자에 의한 결과 = " + ~num1); // 11111111111111111111111111110111, -9
System.out.println("<< 연산자에 의한 결과 = " + (num1 << 2)); // 32 = 00000000000000000000000000100000
System.out.println(">> 연산자에 의한 결과 = " + (num2 >> 2)); // -2 = 11111111111111111111111111111110(부호 유지를 위해 상위값 그대로 유지하며 숫자 추가됨)
System.out.println(">>> 연산자에 의한 결과 = " + (num2 >>> 2)); // 1073741822 = 00111111111111111111111111111110
}
}
비트 연산자
- 비트 연산자는 값을 비트 단위로 연산합니다.
- 따라서 0과 1로 표현이 가능한 정수형이나 형변환이 가능한 자료형만 연산이 가능합니다.
조건 연산자
- 삼항 연산자 : 조건식 ? 반환값1 : 반환값2
- 조건식의 결과에 따라 연산결과를 달리할 수 있습니다.
class Operator8_1 {
public static void main(String[] args) {
int num1 = 5, num2 = 7;
int result;
result = num1 - num2 > 0 ? num1 : num2;
System.out.println("두 정수 중 더 큰 수는 " + result + "입니다."); // 7
}
}
대입연산자
2진수의 음수표현
- 진수의 음수를 표현하는 방식에는 부호 절대값, 1의 보수, 2의 보수가 있습니다.
8비트 기준
부호 절대값
- 가장 왼쪽에 있는 비트를 부호비트라고 했을 때 이 부호비트가 '0인지 1인지' 에 따라 양수, 음수로 구분됩니다.
- 0일때는 양수 , 1일때는 음수
2진수 00000011 = 10진수: 3
2진수 10000011 = 10진수: -3
1의 보수
- 1의 보수는 11111111 - x 를 하는 방식입니다.
- 11111111 - x 는 x 를 반전시킨 것과 같습니다.
즉, 1이면 0, 0이면 1이 됩니다.
2의 보수
- 가장 많이 사용하는 방식입니다.
- 2의 보수는 100000000 - x 를 하는 방식입니다.
- 2의 보수 방식도 가장 왼쪽숫자가 0일 경우 양수, 1일 경우 음수를 표현합니다.
- 쉽게 계산하는 방법은 1의 보수를 구한뒤에 나온수에 +1을 하면 됩니다.