Random 클래스를 이용하면 여러 가지 자료형에 대해서 랜덤 난수를 생성할 수 있습니다.
( import를 해줘야 사용할 수 있습니다. )
random.nextBoolean(); // true 아니면 false를 생성 random.nextInt(); // Int 형 범위에서 정수를 랜덤하게 생성 random.nextInt(N); // 0 ~ N - 1 범위에서 정수를 랜덤하게 생성 random.nextLong(); // Long 형 범위에서 정수를 랜덤하게 생성 random.nextFloat(); // 0.0F ~ 1.0F 사이에서 실수를 랜덤하게 생성 random.nextDouble(); // 0.0D ~ 1.0D 사이에서 실수를 랜덤하게 생성
가장 자주 쓰이는 메소드는 nextInt() 함수로 매개변수를 통해 범위를 지정할 수 있습니다.
물론, 이 난수들은 유사 난수(Pseudo Random Number)입니다. 즉, 컴퓨터가 가지고 있는 랜덤 알고리즘에 의해서 생성되는 난수들이지 정말 랜덤하게 생성되는 수는 아닙니다.
package Hello;
import java.util.Random;
public class randomTest {
public static void main(String args[]) {
Random random = new Random();
System.out.println("nextBoolean : " + random.nextBoolean());
System.out.println("nextInt : " + random.nextInt());
System.out.println("nextInt : " + random.nextInt(100));
System.out.println("nextLong: " + random.nextLong());
System.out.println("nextFloat : " + random.nextFloat());
System.out.println("nextDouble : " + random.nextDouble());
}
}
Math 클래스는 java.lang 패키지에 있으므로 별도로 import 할 필요는 없습니다. 또, Math 클래스의 random() 메소드는 Static 메소드이므로 객체를 생성하지않고 사용할 수 있습니다.
Math.random() 메소드는 0.0D ~ 1.0D 난수를 발생합니다.
package Hello;
public class randomTest {
public static void main(String args[]) {
System.out.println("Math 클래스 난수 : " + Math.random());
}
}
Math 클래스 난수 : 0.9956712501922751
그럼 Math.random() 함수를 이용해서 0 ~ 9 사이의 숫자를 랜덤하게 얻고 싶으면 어떻게 해야 할까요?
package Hello;
public class randomTest {
public static void main(String args[]) {
System.out.println("Math 클래스 난수(0~9사이 정수 난수발생) : " + (int)(10*Math.random()));
}
}
비트 연산자는 각각의 비트를 대상으로연산을 진행하는 연산자이며 피연산자는 반드시 정수이어야 합니다. 실수를 대상으로 하는 비트 연산은 의미가 없기에 자바에서 지원하지 않습니다.
비트 연산자 : &, |, ^, ~
연산자
연산자의 기능
결합 방향
&
비트 단위로 AND 연산을 한다.
→
|
비트 단위로 OR 연산을 한다.
→
^
비트 단위로 XOR 연산을 한다.
→
~
피연산자의 모든 비트를 반선시켜서 얻은 결과를 반환한다.
←
예제 1)
package Hello;
public class HelloWorld {
public static void main(String args[]) {
int a = 8; // 1000(2)
int b = 4; // 100(2);
System.out.printf("a & b : %d\n", a & b);
System.out.printf("a | b : %d\n", a | b);
System.out.printf("a ^ b : %d\n" , a ^ b);
System.out.printf("~a : %d" , ~a);
}
}
+, - 는 이항 연산자로 사용되면 덧셈과 뺄셈에 사용되지만, 단항 연산자로 수학에서와 동일한 의미를 갖습니다. 이때, 자바는 기본적으로 정수형 연산을 int 형으로 진행하고 그 결과도 int 형으로 반환하고, 실수형 연산을 double형으로 진행하고 그 결과도 double 형으로 반환하므로 부호 연산자를 사용할 때도 이 점을 주의해야 합니다.
예시 1)
package Hello;
public class HelloWorld {
public static void main(String args[]) {
int num = 5;
System.out.println(-num);
}
}
-5
위의 코드는 부호 연산자 - 를 이용해 num 의 부호를 바꿔서 출력했습니다.
package Hello;
public class HelloWorld {
public static void main(String args[]) {
short num = 5;
short num2 = -num;
}
}
위의 코드를 실행하면 num2 에는 -5가 저장될까요? 정답은 -num 은 int 형이지만 num2 는 short 형이므로 에러가 발생합니다.
증가 및 감소 연산자 : ++, --
연산자
연산자의 기능
결합 방향
++ (Prefix)
피연산자에 저장된 값을 1 증가시킵니다.
val = ++n;
←
-- (Prefix)
피연산자에 저장된 값을 1 감소시킵니다.
val = --n;
←
++ (Postfix)
피연산자에 저장된 값을 1 증가시킵니다.
val = n++;
←
-- (Postfix)
피연산자에 저장된 값을 1 감소시킵니다.
val = n--;
←
증가 및 감소 연산자 ++, -- 는 피연산자의 앞부분에 붙이냐, 뒷부분에 붙이냐에 따라 작동하는 방식이 조금 다릅니다. 기본적으로 값이 하나 증가 및 감소하는 것은 동일하나 반영되는 시점에 차이가 있습니다. Prefix 방식은 연산으로 인한 값의 증가 및 감소가 연산이 진행된 문장에서 발생하고, Postfix 방법은 그다음 문장으로 넘어가야 반영이 됩니다.
관계 연산자는 두 개의 피연산자 사이에서 크기 및 동등 관계를 따져주는 이항 연산자로 결과에 따라서 true 또는 false를 반환합니다.
연산자
연산자의 기능
결합 방향
<
a < b
a 가 b 보다 작은가?
→
>
a > b
a 가 b 보다 큰가?
→
<=
a <= b
a 가 b 보다 작거나 같은가
→
>=
a >= b
a 가 b 보다 크거나 같은가
→
==
a == b
a 가 b 랑 같은가?
→
!=
a != b
a 가 b랑 다른가?
→
논리 연산자 : &&, ||, !
연산자
연산자의 기능
결합 방향
&&
A && B
A와 B 모두가 true이면 true, 아니면 false ( 논리 AND 와 동일 )
→
||
A || B
A와 B 모두가 false이면 false, 아니면 true ( 논리 OR 과 동일 )
→
!
!A
A가 true이면 false, false이면 true 반환 ( 논리 NOT )
→
예시 1)
package Hello;
public class HelloWorld {
public static void main(String args[]) {
int num1 = 0;
int num2 = 0;
boolean result;
result = ((num1 += 10) < 0) && ((num2 += 10) > 0);
System.out.println(result);
System.out.println(num1);
System.out.println(num2);
}
}
위의 출력 결과는 어떻게 될까요?
false
10
0
num1은 10이지만, num2는 0인 것을 확인할 수 있습니다. 그 이유는 && 연산자 때문입니다. ( (num1 += 10) < 0 ) 이 먼저 수행되는데, num1 += 10을 하면 num1은 10이 되므로 0보다 작지 않습니다. 따라서 ( (num1 += 10) < 0 ) 은 false가 됩니다. 이때, && 연산자는 false가 하나라도 존재하면 어차피 false 값을 같습니다. 따라서 ( (num2 += 10) > 0) 연산을 진행하지 않고 result 에는 false가 저장됩니다.
예시 2)
package Hello;
public class HelloWorld {
public static void main(String args[]) {
int a = 5; // 코드 1번
System.out.println(a++); // 코드 2번
System.out.println(a); // 코드 3번
System.out.println((a++ + 5) * 3); // 코드 4번
a = (a++ + 5) * 3; // 코드 5번
System.out.println(a); // 코드 6번
}
}
위의 코드는 어떤 값들을 출력할까요? 정답은 아래와 같습니다!
5
6
33
36
코드 1번에서 a 에 5를 할당합니다.
코드 2번에서는 a를 출력한 후, ++ 연산이 진행되므로 '5'를 출력하지만 a의 값은 6이 됩니다.
코드 3번은 코드 2번에 의해 '6' 을 출력하게 됩니다.
코드 4번에는 ( ) , ++, +, * 4가지 연산이 등장합니다. 우선순위는 ( ), ++, *, + 순으로 괄호 안에 식을 먼저 진행해야 됩니다. 따라서 ++ 과 + 연산이 진행되는데 이때, ++ 연산은 명령을 마무리 한 후에 a의 값을 올려주므로 (6 + 5) 가 진행됩니다. 그 후 * 3을 해서 33이라는 값이 만들어지고 a는 1 증가해서 7이 됩니다.
코드 5번은 ( ), ++, +, * , = 5가지 연산이 등장합니다. 우선순위는 ( ), ++, *, +, = 순으로 코드 4번과 마찬가지로 괄호 안에 식을 먼저 진행해야됩니다. 따라서 (7 + 5) 가 먼저 계산되고, 12 * 3이 계산되고 ++ 연산에 의해 a는 1 증가해서 8이 됩니다. 하지만 = 연산에 의해 계산된 36이란 값이 a에 저장되므로 a는 결국 36이 저장됩니다.
예시 3)
package Hello;
public class HelloWorld {
public static void main(String args[]) {
int a = 1; // 코드1
a = ~a; // 코드2
System.out.println(a); // 코드3
}
}
위의 예시는 어떤 값을 출력할까요?
-2
정답은 '-2' 입니다.
컴퓨터는 모든 숫자를 2진수로 저장합니다. 우리는 앞의 포스팅에서 int 는 4바이트로 이루어져 있다고 배웠습니다. 따라서, a에 1을 할당하면 다음과 같이 컴퓨터에는 저장됩니다.
a = 0000 0000 0000 0000 0000 0000 0000 0001 (2)
~ 연산은 쉽게 말하면 2진수로 저장된 a의 비트들을 반대로 바꿔주는 연산입니다. 즉, 코드2에 의해 a는 다음과 같이 바뀝니다.
a = 1111 1111 1111 1111 1111 1111 1111 1110 (2)
컴퓨터가 정수는 저장하는 방법인 2의 보수법에 의하면 위의 2진수 코드는 '-2' 를 의미합니다. 따라서 -2가 출력됩니다.
예시 4) 비트 연산자
<< 연산자는 비트 값들을 왼쪽으로 이동시킨 후에 오른쪽의 빈 공간에는 모두 0으로 채운다.
>> 연산자는 비트 값들을 오른쪽으로 이동시킨 후에 왼쪽의 빈 공간에 양수라면 0으로, 음수라면 1로 채워줍니다.
>>> 연산자는 비트 값들을 오른쪽으로 이동시킨 후에 부호와 상관없이 0으로 채워줍니다.
package Hello;
public class HelloWorld {
public static void main(String args[]) {
int a = 1; // 코드1
a = a << 5; // 코드2
System.out.println(a);
a = a >> 3; // 코드3
System.out.println(a);
int b = -2147483648; // 코드4
b = b >> 1; // 코드5
System.out.println(b);
int c = -2147483648; // 코드6
c = c >>> 1; // 코드7
System.out.println(c);
}
}
위의 예시는 어떤 값들을 출력할까요?
32
4
-1073741824
1073741824
코드1에서 a에 1을 할당하므로 a = 0000 0000 0000 0000 0000 0000 0000 0001 (2) 가 됩니다.
코드2에 의해 a는 왼쪽으로 5칸씩 비트가 이동하게 되고, 오른쪽의 파란 부분에는 0이 채워지고 위의 노란 부분에 해당하는 비트들은 사라지게 됩니다.
a = 0000 0000 0000 0000 0000 0000 0010 0000 (2)
따라서, 현재 a는 10진법으로 32를 나타냅니다.
코드3에 의해 a는 오른쪽으로 3칸씩 비트가 이동하게 되고, 양수이므로 왼쪽의 빨간 부분에 0이 채워지게 됩니다.
a =0000 0000 0000 0000 0000 0000 0000 0100 (2)
따라서, 현재 a는 10진법으로 4를 나타냅니다.
코드4에서 b에 -2147483648 을 할당하므로 b = 1000 0000 0000 0000 0000 0000 0000 0000(2) 가 됩니다.
코드5에서 >> 연산은 음수 값은 왼쪽의 비는 부분을 1로 채우므로 b = 1100 0000 0000 0000 0000 0000 0000 0000(2) 가 되고, 10진수로 표현하면 -1073741824 가 됩니다.
코드6에서 c = 1000 0000 0000 0000 0000 0000 0000 0000(2) 가 됩니다.
코드7에서 >>> 연산은 부호에 상관 없이 왼쪽의 비는 부분을 0으로 채우므로 c = 0100 0000 0000 0000 0000 0000 0000 0000(2) 가 됩니다. 부호를 나타내는 맨 앞 코드가 0이 되어서 c는 양수가 되고 10진수로 표현하면 1073741824가 됩니다.