// +: 피연산자의 부호 유지
// -: 피연산자의 부호 변경
// 2. 부호를 변경하는 것도 연산
byte b = 100;
// 아래 코드는 컴파일 에러 발생
// byte, short, int 연산의 결과는 int 타입이어야 하므로
byte result = -b;
// 선행증감: ++,--를 먼저 수행
// 후행증감: ++,--를 나중에 수행 (다른 연산을 먼저 수행한다.)
int x = 1;
int y = 1;
int result1 = ++x + 10; // x를 1증가한 뒤 10을 더해준다.
int result2 = y++ + 10; // y에 10을 더한다. 이후 y값은 1에서 2로 바뀜
x++;
++x; // 단지 변수 단독으로 증감 연산 수행 => 앞 뒤 모두 결과가 동일하다.
int x = 10;
int z = x++; // z= 10, x= 11이 된다. 대입도 연산이기 때문이다.
int X = 10;
int z = ++x; // z와 x 값 모두 11이 된다. 증감식 먼저 수행한 뒤 대입을 수행하기 때문이다.
// +, -, *, /, %로 총 5개의 산술 연산자가 존재
// 5. 산술 연산의 특징
// byte, short, char, int의 연산은 결과가 항상 int 타입이다.
// but 그 중 하나가 long 타입이면 연산의 결과는 long이다.
// 피연산자 중 하나가 실수 타입이면 연산의 결과는 실수 타입이다.
// 예시 코드
public class ArithmeticOperations {
public static void main(String[] args) {
// byte, short, char, int의 연산은 결과가 항상 int 타입
byte byteValue1 = 10;
byte byteValue2 = 20;
int result1 = byteValue1 + byteValue2; // 결과는 int 타입
System.out.println("Result 1: " + result1);
// 하나가 long 타입이면 결과는 long 타입
int intValue = 30;
long longValue = 40L;
long result2 = intValue + longValue; // 결과는 long 타입
System.out.println("Result 2: " + result2);
// 피연산자 중 하나가 실수 타입이면 결과는 실수 타입
float floatValue = 3.14f;
int intValue2 = 5;
float result3 = floatValue * intValue2; // 결과는 float 타입
System.out.println("Result 3: " + result3);
}
}
// 오버플로우: 타입이 허용하는 최대값을 벗어나는 것이다.
public class OverflowExample {
public static void main(String[] args) {
int maxValue = Integer.MAX_VALUE;
int overflowedValue = maxValue + 1;
System.out.println("Max Value: " + maxValue);
System.out.println("Overflowed Value: " + overflowedValue); // 오버플로우 발생
}
}
// 언더플로우: 타입이 허용하는 최소값을 벗어나는 것이다.
public class UnderflowExample {
public static void main(String[] args) {
int minValue = Integer.MIN_VALUE;
int underflowedValue = minValue - 1;
System.out.println("Min Value: " + minValue);
System.out.println("Underflowed Value: " + underflowedValue); // 언더플로우 발생
}
}
public class DataTypeRanges {
public static void main(String[] args) {
// byte: 8-bit signed integer
byte minValueByte = Byte.MIN_VALUE; // -128
byte maxValueByte = Byte.MAX_VALUE; // 127
System.out.println("byte Range: " + minValueByte + " to " + maxValueByte);
// short: 16-bit signed integer
short minValueShort = Short.MIN_VALUE; // -32768
short maxValueShort = Short.MAX_VALUE; // 32767
System.out.println("short Range: " + minValueShort + " to " + maxValueShort);
// char: 16-bit unsigned integer (but often used to represent characters)
char minValueChar = Character.MIN_VALUE; // 0
char maxValueChar = Character.MAX_VALUE; // 65535 (unsigned)
System.out.println("char Range: " + (int) minValueChar + " to " + (int) maxValueChar);
// int: 32-bit signed integer
int minValueInt = Integer.MIN_VALUE; // -2147483648
int maxValueInt = Integer.MAX_VALUE; // 2147483647
System.out.println("int Range: " + minValueInt + " to " + maxValueInt);
// long: 64-bit signed integer
long minValueLong = Long.MIN_VALUE; // -9223372036854775808
long maxValueLong = Long.MAX_VALUE; // 9223372036854775807
System.out.println("long Range: " + minValueLong + " to " + maxValueLong);
// float: 32-bit single-precision floating-point
float minValueFloat = Float.MIN_VALUE; // 1.4E-45
float maxValueFloat = Float.MAX_VALUE; // 3.4028235E38
System.out.println("float Range: " + minValueFloat + " to " + maxValueFloat);
// double: 64-bit
double-precision floating-point
double minValueDouble = Double.MIN_VALUE; // 4.9E-324
double maxValueDouble = Double.MAX_VALUE; // 1.7976931348623157E308
System.out.println("double Range: " + minValueDouble + " to " + maxValueDouble);
}
}
public class FloatingPointError {
public static void main(String[] args) {
// 정확한 10진수 표현이 어려운 경우
double result1 = 0.1 + 0.2;
System.out.println("0.1 + 0.2 = " + result1); // 결과: 0.30000000000000004
// 정확한 10진수 표현이 어려운 경우
double result2 = 1.0 - 0.9;
System.out.println("1.0 - 0.9 = " + result2); // 결과: 0.09999999999999998
}
}
이 코드에서 0.1 + 0.2
와 1.0 - 0.9
는 각각 예상과 다르게 결과가 나타납니다. 이는 부동 소수점 표현 방식에서 정확한 10진수 표현이 어렵기 때문에 발생하는 오차입니다.
=> 정확한 계산을 위해 정수 연산을 사용하자.
public class NaNExample {
public static void main(String[] args) {
double result1 = 0.0 / 0.0; // NaN (0으로 나누기)
double result2 = Math.sqrt(-1.0); // NaN (음수의 제곱근)
System.out.println("Result 1: " + result1); // NaN
System.out.println("Result 2: " + result2); // NaN
// NaN인지 확인
if (Double.isNaN(result1)) {
System.out.println("Result 1 is NaN");
}
// NaN을 특정 값으로 대체
double replacementValue = 10.0;
result1 = Double.isNaN(result1) ? replacementValue : result1;
System.out.println("Result 1 (after replacement): " + result1); // 대체된 값
}
}
public class InfinityExample {
public static void main(String[] args) {
double positiveInfinity = 1.0 / 0.0; // 양의 무한대
double negativeInfinity = -1.0 / 0.0; // 음의 무한대
System.out.println("Positive Infinity: " + positiveInfinity); // Infinity
System.out.println("Negative Infinity: " + negativeInfinity); // -Infinity
// Infinity인지 확인
if (Double.isInfinite(positiveInfinity)) {
System.out.println("Positive Infinity");
}
// Infinity를 특정 값으로 대체
double replacementValue = 100.0;
positiveInfinity = Double.isInfinite(positiveInfinity) ? replacementValue : positiveInfinity;
System.out.println("Positive Infinity (after replacement): " + positiveInfinity); // 대체된 값
}
}
위 코드에서 Double.isNaN()
은 NaN 여부를 확인하고, Double.isInfinite()
는 Infinity 여부를 확인합니다. 이러한 메서드를 사용하여 특별한 값들을 처리하거나 대체할 수 있습니다.
크기 비교와 동등 비교 연산자는 자바에서 각각 <
, >
, <=
, >=
, ==
, !=
로 표현됩니다.
<
, >
, <=
, >=
):public class ComparisonOperators {
public static void main(String[] args) {
int a = 5;
int b = 10;
// 크기 비교 연산자 사용
System.out.println("a < b: " + (a < b)); // true
System.out.println("a > b: " + (a > b)); // false
System.out.println("a <= b: " + (a <= b)); // true
System.out.println("a >= b: " + (a >= b)); // false
}
}
==
, !=
):public class EqualityOperators {
public static void main(String[] args) {
int x = 5;
int y = 5;
// 동등 비교 연산자 사용
System.out.println("x == y: " + (x == y)); // true
System.out.println("x != y: " + (x != y)); // false
String str1 = "Hello";
String str2 = "World";
// 문자열의 동등 비교
System.out.println("str1.equals(str2): " + str1.equals(str2)); // false
}
}
위 코드에서는 크기 비교 연산자와 동등 비교 연산자를 각각의 상황에 맞게 사용한 예시입니다. 크기 비교 연산자는 숫자 비교에 사용되며, 동등 비교 연산자는 값이 같은지 여부를 판단하는 데 사용됩니다. 문자열의 경우에는 equals
메서드를 사용하여 동등 비교를 수행합니다.
자바에서는 논리 연산자를 사용하여 논리적인 조건을 다양하게 조합할 수 있습니다. 주요 논리 연산자로는 &&
(논리 AND), ||
(논리 OR), !
(논리 NOT)이 있습니다.
&&
):public class LogicalAndOperator {
public static void main(String[] args) {
int age = 25;
boolean isStudent = true;
// 논리 AND 연산자 사용
boolean result = (age > 18) && isStudent;
System.out.println("Result: " + result); // true
}
}
||
):public class LogicalOrOperator {
public static void main(String[] args) {
int temperature = 25;
boolean isSunny = false;
// 논리 OR 연산자 사용
boolean result = (temperature > 30) || isSunny;
System.out.println("Result: " + result); // false
}
}
!
):public class LogicalNotOperator {
public static void main(String[] args) {
boolean isRaining = true;
// 논리 NOT 연산자 사용
boolean result = !isRaining;
System.out.println("Result: " + result); // false
}
}
위의 코드에서는 논리 AND, OR, NOT 연산자를 사용하여 각각의 조건을 평가하고 결과를 출력하고 있습니다. 논리 연산자는 조건문, 반복문 등 다양한 상황에서 사용되어 프로그램의 흐름을 제어하는 데 유용합니다.
^
):public class LogicalXorOperator {
public static void main(String[] args) {
boolean condition1 = true;
boolean condition2 = false;
// 배타적 논리합 연산자 사용
boolean result = condition1 ^ condition2;
System.out.println("Result: " + result); // true
}
}
이 코드에서 ^
연산자는 두 피연산자 중 하나만 참일 때 결과가 참이 되도록 동작합니다. 위 예시에서는 condition1
이 참이고 condition2
가 거짓이므로 결과는 참(true
)이 됩니다.
비트 논리 연산자는 비트 단위로 연산을 수행하는 연산자로서 &
(AND), |
(OR), ^
(XOR), ~
(NOT) 등이 있습니다.
&
):public class BitwiseAndOperator {
public static void main(String[] args) {
int a = 5; // 이진수: 0101
int b = 3; // 이진수: 0011
// 비트 AND 연산자 사용
int result = a & b;
System.out.println("Result: " + result); // 1 (이진수: 0001)
}
}
|
):public class BitwiseOrOperator {
public static void main(String[] args) {
int a = 5; // 이진수: 0101
int b = 3; // 이진수: 0011
// 비트 OR 연산자 사용
int result = a | b;
System.out.println("Result: " + result); // 7 (이진수: 0111)
}
}
^
):public class BitwiseXorOperator {
public static void main(String[] args) {
int a = 5; // 이진수: 0101
int b = 3; // 이진수: 0011
// 비트 XOR 연산자 사용
int result = a ^ b;
System.out.println("Result: " + result); // 6 (이진수: 0110)
}
}
~
):public class BitwiseNotOperator {
public static void main(String[] args) {
int a = 5; // 이진수: 0101
// 비트 NOT 연산자 사용
int result = ~a;
System.out.println("Result: " + result); // -6 (이진수: 11111111111111111111111111111010)
}
}
비트 논리 연산자는 정수형 데이터 타입에서 각 비트를 처리하는 데 사용되며, 주로 저수준 프로그래밍이나 비트 조작이 필요한 상황에서 활용됩니다.
비트 이동 연산자는 비트 단위로 특정 방향으로 비트를 이동시키는 연산자로서, 자바에서는 <<
(왼쪽 시프트), >>
(오른쪽 시프트), >>>
(부호 없는 오른쪽 시프트)가 있습니다.
<<
):public class LeftShiftOperator {
public static void main(String[] args) {
int num = 5; // 이진수: 0000 0101
// 왼쪽 시프트 연산자 사용
int result = num << 2;
System.out.println("Result: " + result); // 20 (이진수: 0001 0100)
}
}
>>
):public class RightShiftOperator {
public static void main(String[] args) {
int num = 16; // 이진수: 0001 0000
// 오른쪽 시프트 연산자 사용
int result = num >> 2;
System.out.println("Result: " + result); // 4 (이진수: 0000 0100)
}
}
>>>
):public class UnsignedRightShiftOperator {
public static void main(String[] args) {
int num = -8; // 이진수: 1111 1000
// 부호 없는 오른쪽 시프트 연산자 사용
int result = num >>> 2;
System.out.println("Result: " + result); // 1073741822 (이진수: 0011 1111 1111 1111 1111 1111 1111 1110)
}
}
비트 이동 연산자는 주로 특정 비트 패턴을 원하는 방향으로 이동시키거나, 연산을 최적화하는 데 사용됩니다.
자바에서 제공하는 11가지 복합 대입 연산자들은 다음과 같습니다:
+=
(덧셈 후 대입): num1 += num2; // num1 = num1 + num2;
-=
(뺄셈 후 대입): num1 -= num2; // num1 = num1 - num2;
*=
(곱셈 후 대입): num1 *= num2; // num1 = num1 * num2;
/=
(나눗셈 후 대입): num1 /= num2; // num1 = num1 / num2;
%=
(나머지 연산 후 대입): num1 %= num2; // num1 = num1 % num2;
&=
(비트 AND 후 대입): num1 &= num2; // num1 = num1 & num2;
|=
(비트 OR 후 대입): num1 |= num2; // num1 = num1 | num2;
^=
(비트 XOR 후 대입): num1 ^= num2; // num1 = num1 ^ num2;
<<=
(왼쪽 시프트 후 대입): num1 <<= num2; // num1 = num1 << num2;
>>=
(오른쪽 시프트 후 대입): num1 >>= num2; // num1 = num1 >> num2;
>>>=
(부호 없는 오른쪽 시프트 후 대입): num1 >>>= num2; // num1 = num1 >>> num2;
public class TernaryOperator {
public static void main(String[] args) {
int num1 = 5;
int num2 = 10;
// 삼항 연산자 사용
int result = (num1 > num2) ? num1 : num2;
System.out.println("Result: " + result); // 10
}
}
자바에서 연산자는 특정 방향과 우선순위를 가지고 있습니다. 이러한 규칙을 따라 표현식이 계산되며, 연산자 우선순위에 따라 어떤 연산이 먼저 수행되는지 결정됩니다.
연산자의 방향:
1. 단항 연산자 방향: 단항 연산자(++, --, ! 등)는 피연산자의 왼쪽에 위치합니다.
2. 이항 연산자 방향: 대부분의 이항 연산자(+, -, *, / 등)는 좌측에서 우측으로 피연산자를 취합니다.
연산자의 우선순위:
1. Postfix(후위) 및 Prefix(전위) 연산자: ++, --
2. Multiplicative(곱셈, 나눗셈, 나머지) 연산자: , /, %
3. Additive(덧셈, 뺄셈) 연산자: +, -
4. Shift(시프트) 연산자: <<, >>, >>>
5. Relational(관계) 연산자: <, >, <=, >=, instanceof
6. Equality(동등) 연산자: ==, !=
7. Bitwise AND: &
8. Bitwise XOR: ^
9. Bitwise OR: |
10. Logical AND: &&
11. Logical OR: ||
12. Conditional(삼항) 연산자: ?:
13. Assignment(할당) 및 Compound Assignment(복합 할당) 연산자: =, +=, -=, =, /=, %=, &=, ^=, |=, <<=, >>=, >>>=
14. 증가 및 감소 연산자: ++, --
이러한 우선순위와 방향을 이용하여 표현식의 계산 순서를 이해할 수 있습니다. 필요에 따라 괄호를 사용하여 우선순위를 변경할 수도 있습니다.