2014년 9월 4일 목요일

Java 연산자(그 밖의 연산자)

6. 그 외의 연산자

6.1 삼항 연산자 ? :


삼항 연산자는 세 개의 피연산자를 필요로 하기 때문에 삼항 연산자입니다. 조건식과 조건식이 참일 때와 거짓 일 때 반환되는 값 이 세가지가 삼항연사자의 피연사자입니다. 삼항 연산자의 조건식에는 연산결과가 ture 또는 false인 식이 사용되어야 합니다.
 조건식의 연산결과가 true이면 식 1을 결과로 얻고 false이면 식2를 결과로 얻습니다.

(조건식) ? 식1 : 식2
result = (x>0)? x : -x;

삼항 연산자는 if문으로 바꿔 쓸 수 있으며, 간단한 if문 대신 삼항 연산자를 사용하면 코드를 간단히 할 수 있습니다.
 위의 삼항연산자를 if문으로 바꾸면 다음과 같이 됩니다

if(x>0){
result = x;
}else{
result=-x;
}

삼항연산자

public class Operator27 {

public static void main(String[] args) {

int x = 10;
int y = -10;

int X = ( x>=0 ? x : -x);
int Y = ( y>=0 ? y : -y);

System.out.println("x=10일 때. x의 절대값은 "+X);
System.out.println("y=10일 때, y의 절대값은 "+Y);

}
}

실행결과

x=10일 때. x의 절대값은 10
y=10일 때, y의 절대값은 10

삼항 연산자를 이용해서 변수의 절대값을 구하는 예제입니다.
삼항 연산자를 대신 조건문을 사용하면
int X=0;
if(x>=0){
X=x}else{
X=-x;
}

6.2 대입 연산자 =,op=


대입 연산자는 변수에 값 또는 수식의 연산결과를 저장하는데 사용됩니다. 대입 연산자의 왼쪽에는 반드시 변수가 위치하고 오른쪽에는 리터럴이나 변수 또는 수식이 옵니다.

int x = 0;
x = 3
x = x+3;
7 = x+4;  // 대입 연산자의 왼쪽 피연산자가 변수가 아니기 때문에 에러가 난다.
final X = 3; //final을 붙이면 상수가 됩니다.
X = 10  // 상수의 값은 바꿀 수 없습니다.

변수 앞에 키워드 'final'을 붙이면 상수(constant)가 됩니다. 상수는 선언과 동시에 값을 저장해야하며 한 번 저장된 값은 바꿀 수 없습니다.

대입 연산자는 모든 연산자들 중에서 가장 낮은 연산순위를 가지고 잇기 때문에 제일 마지막에 수행됩니다. 연산진행방향은 오른쪽에서 왼쪽이기 때문에 x=y=3;에서 y=3이 먼저 수행되고 그 다음에 x=y가 수행됩니다.
대입 연산자는 다른 연산자와 결합하여 'op='와 같은 방식으로 사용이 될 수 있습니다.
x = x+7은 x +=7과 같이 표현할 수 있습니다.

Java 연산자(논리연산자)

5. 논리 연산자

5.1 논리 연산자 &&, ll

논리 연산자는 피연산자로 boolean형 또는 boolean형 값을 결과로 하는 조건식만을 허용한다. 조건문과 반복문에서 조건식 간의 결합에 사용합니다.
 그리고 &&가 ll연산보다 우선순위가 높으므로 한 조건식에 &&와 ll가 함께 사용할 떄는 관호를 사용해서 우선순위를 명확하게 해주도록 합니다.

ll(or 결합) - 피연산자 중 어느 한 쪽만 true이면 true를 결과로 얻습니다.
&&(and 결합) - 피연산자 양쪽 모두 true이어야 true를 결과로 얻습니다.

논리 연산자의 또 다른 특징은 효율적인 연산을 한다는 것입니다. or연산 ll의 경우, 두 개의 피연산자 중 어느 한 쪽만 true가 되어도 전체 연산결과가 true가 되므로 좌측의 피연산자가 true면, 우측의 피연사자의 값은 검사하지 않습니다. and연산 &&의 경우도 마찬가지로 어느 한쪽만 false이어도 전체 연산결과가 false이므로 좌측의 피연사자가 false면, 우측의 피연산자의 값은 검사하지 않습니다.
즉 같은 조건식이라도 피연산자의 위치에 따라서 연산속도가 달라질 수 있습니다.

public class Operator23 {

public static void main(String[] args) {

char x = 'e';

if((x>='a' && x<='z') || x>='a' &&  x<='z')
System.out.println("유효한 문자입니다.");
else
System.out.println("유요하지 않은 문자입니다.");


}


}

실행결과

유요하지 않은 문자입니다.

&&와 ||를 조합하여 e가 유요한 영문자인지를 검사하는 조건식을 만들었습니다. 문자형 변수 x에 저장된 문자가 'e'이므로 or연산자의 좌측 피연산자인 조건식(x>='a'&&x<='z')의 결과가 true이기 때문에 나머지 우측 연산자를 검사하지 않고 전체 조건식을 true로 판단합니다.

5.2 비트 연산자 & | ^


비트 연산자는 이진 비트연산을 수행합니다. 값을 이진수로 표현했을 때의 각 자리수의 규칙에 따라 연산을 수행합니다. 실수형인 float와 doulble을 제외한 모든 기본형에서 사용가능합니다.

| (or연산자) : 피연산자 중 한쪽 값이 1이면, 1을 결과로 얻고, 그 외에는 0을 얻습니다.
&(and연산자) : 피연산자 양 쪽이 모두 1이어야 1을 결과로 얻고, 그 외에는 0을 얻습니다.
^(xor연산자) : 피연산자의 값이 서로 다를 때만 1을 결과로 얻고, 그 외에는 0을 얻습니다.


public class Operator23 {

public static void main(String[] args) {
int x = 3;
int y = 7;
System.out.println("x는 "+x+"이고, "+"y는 "+y+"일 때,");
System.out.println("x | y = " +(x|y));
System.out.println("x & y = " +(x&y));
System.out.println("x ^ y = " +(x^y));
System.out.println("true | false= "+(true|false));
System.out.println("true & false= "+(true&false));
System.out.println("true ^ false= "+(true^false));
}

}

실행결과

x는 3이고, y는 7일 때,
x | y = 7
x & y = 3
x ^ y = 4
true | false= true
true & false= false
true ^ false= true

논리 연산자는 덧셈연산자'+'보다 연산우선순위가 낮기 때문에 괄호를 사용해야합니다.



Java 연산자(비교연산자)

4. 비교 연산자

비교 연산자는 두 개의 변수 또는 리터럴을 비교하는데 사용되는 연산자로 주로 조건문과 반복문의 조건식에 사용되며, 연산결과는 true 또는 false입니다.
 비교 연산자 역시 이항 연산자이므로 비교하는 피ㅣ연산자의 자료형이 서로 다를 경우에는 자료형의 범위가 큰 쪽으로 형변환하여 피연산자의 타입을 일치시킨 후에 비교합니다.

4.1 대소비교 연산자 >, <, <=, >=

두 연산자의 크기를 비교하는 연산자이다. 기본형 중에서너는 boolean형을 제외한 나머지 자료형에 다 사용할 수 있지만 참조형은 사용할 수 없습니다.

4.2 등가비교 연산자 ==, !=


두 피연산자에 저장되어 있는 값이 다른지 혹은 다른지를 비교하는 연사자입니다. 대소비교연산자와는 달리, 모든 자료형에 사용할 수 있습니다. 기본형의 경우 변수에 저장되어 있는 값이 같은지를 알 수 있고, 참조형의 경우 객체의 주소값을 저장하기 때문에 두 개의 피연사자가 같은 객체를 가리키고 있는지를 알 수 있습니다.
기본형과 참조형 간에는 서로 형변환이 불가능 하기 때문에 등가비교 연산자(==, !=)의 피연산자로 기본형과 참조형을 함께 사용할 수 없습니다.

public class Operator23 {

public static void main(String[] args) {

if(10 == 10.0f){
System.out.println("10과 10.0은 같습니다.");
}
if('0' != 0){
System.out.println("'0'과 0은 같지 않습니다.");
}
if('A' == 65){
System.out.println("'A'는 65와 같습니다.");
}
int a=5;
if(a>0 && a<10){
System.out.println("5는 0보다 크고 10보다 작습니다.");
}
}

}

실행결과

10과 10.0은 같습니다.
'0'과 0은 같지 않습니다.
'A'는 65와 같습니다.
5는 0보다 크고 10보다 작습니다.

비교 연산자에서도 연산을 수행하기 전에 형변환을 통해 피연산자의 타입을 맞춤 다음 피연산자를 비교합니다. 10==10.0f에서 10은 int이고 10.0f는 float이므로 int형인 10을 float형으로 변환한 다음 비교합니다. 두개의 값이 서로 같으므로 결과로 true를 얻게 되는 것입니다. 또한 'A'==65는 'A'를 int로 변환하여 65의 값을 얻고 65==65을 계산하므로 true를 얻게 됩니다.

public class Operator23 {

public static void main(String[] args) {
float a = 0.1f;
double b = 0.1;
double c = (double)a;
System.out.println("10.0==10.0f ? "+(10.0==10.0f));
System.out.println("0.1==0.1f ? " +(0.1==0.1f));
System.out.println("a="+a);
System.out.println("b="+b);
System.out.println("c="+c);
System.out.println("a==b ? " +(a==b));
System.out.println("b==c ? " +(b==c));
System.out.println("c==a ? " +(c==a));
}

}

실행결과

10.0==10.0f ? true
0.1==0.1f ? false
a=0.1
b=0.1
c=0.10000000149011612
a==b ? false
b==c ? false
c==a ? true

10.0==10.0f는 true인데 0.1==0.1f는 false라는 결과가 나왔다. 정수형과 달리 실수형이 float와 double의 값은 근사값으로 저장되기 때문에 이런 결과가 나오는데, 10.0f을 double로 변환하면 10.0을 얻지만, 0.1f를 double로 변환하면 0.1이 아닌 0.10000000149011612을 얻는다. 이값은 0.1에 상당히 가갑지만 정확한 0.1이 아니기 때문에 false로 출력된다.
이 정도의 오차는 산술계산에서는 무시할 수 있을 정도로 아주 작은 것이지만 값의 크기와 같고 다름을 판단하는 비교연산자에서는 문제가 된다. 따라서 이 문제를 해결하기 위해서 형변환을 통해 두 피연산자의 타입을 flaot로 맞춰 비교연산과정에서 형변환이 일어나지 않도록 하거나, 소수점 몇 째 자리까지 동일하게 잘라서 비교해야합니다.

Java 연산자(산술연산자-쉬프트연산자)

3.3 쉬프트 연산자

쉬프트 연산자는 정수형 변수에만 사용할 수 잇습니다. 피연산자의 각 자리(2진수로 표현했을 때)를 오른쪽 또는 왼쪽으로 이동(shift)한다고 해서 쉬프트 연산자라고 불린다. 오른쪽으로 n자리를 이동하면 피연산자를 2^n로 나눈 것과 같은 결과를, 왼쪽으로 n자리를 이동하면 2^n으로 곱한 것과 같은 결과를 얻습니다.

x << n은 x*2^n의 결과와 같다.
x >> n은 x/2^n의 결과와 같다

<<연산자의 경우, 피연산자의 부호에 상관없이 자리를 왼쪽으로 이동시키며 빈칸을 0으로 채우면 된다. >>연산자의 경우, 오른쪽으로 이동시키기 때문에 음수인 경우 부호를 유지시켜주기 위해서 음수인 경우 빈자리를 1로 채우면 된다. 반면에 >>>연산자의 경우, 부호에 상관없이 항상 0으로 빈자리를 채운다.
곱셈이나 나눗셈 연산자를 사용하면 같은 결과를 얻을 수 잇는데, 굳이 쉬프트 연산자를 제공하는 이유는 속도 때문입니다.
예를 들어 8>>>2의 결과는 8/4의 결과와 같지만, 8/4를 연산하는데 걸리는 시간보다 8>>>2를 연산하는데 걸리는 시간이 더 적게 걸립니다. 즉 << 또는 >>을 사용하는 것이 곱셈과 나눗셈 연산자 보다 더 빠릅니다.

public class Operator22
{

public static void main(String[] args) {

int number;
System.out.println(-8);
//-8진수를 2진수 문자열로 변경합니다.
System.out.println(Integer.toBinaryString(-8));
System.out.println();

number = -8 << 1;
System.out.println("-8 << 1 =" +number);
System.out.println(Integer.toBinaryString(number));
System.out.println();

number = -8 << 2;
System.out.println("-8 << 2 =" +number);
System.out.println(Integer.toBinaryString(number));
System.out.println();

System.out.println();
number = -8;
System.out.println(Integer.toBinaryString(number));
System.out.println();

number = -8 >> 1;
System.out.println("-8 >> 1 =" +number);
System.out.println(Integer.toBinaryString(number));
System.out.println();

number = -8 >> 2;
System.out.println("-8 << 1 =" +number);
System.out.println(Integer.toBinaryString(number));
System.out.println();

System.out.println();
number = -8;
System.out.println(Integer.toBinaryString(number));
System.out.println();

number = -8 >>> 1;
System.out.println("-8 >>> 1 =" +number);
System.out.println(Integer.toBinaryString(number));
System.out.println();

number = -8 >>> 2;
System.out.println("-8 >>> 2 =" +number);
System.out.println(Integer.toBinaryString(number));
System.out.println();

}
}

실행결과

-8
11111111111111111111111111111000

-8 << 1 =-16
11111111111111111111111111110000

-8 << 2 =-32
11111111111111111111111111100000


11111111111111111111111111111000

-8 >> 1 =-4
11111111111111111111111111111100

-8 << 1 =-2
11111111111111111111111111111110


11111111111111111111111111111000

-8 >>> 1 =2147483644
1111111111111111111111111111100

-8 >>> 2 =1073741822
111111111111111111111111111110

-8>>>1과 -8>>>2의 결과에서 맨 앞의 0은 생략된 것이다. Integer.toBinaryString(int i)는 정수 2진수 문자열로 변환할 때 앞부분의 0은 생락합니다.

2014년 9월 3일 수요일

Java 연산자(산술연산자-나머지연산자)

3.2 나머지 연산자

왼쪽의 피연산자를 오늘쪽 피연산자로 나누고 난 나머지 값을 돌려주는 연산자입니다.
boolean형을 제외하고는 모든 기본형 변수에 사용할 수 있습니다. 나머지 연산자는 주로 짝수, 홀수 또는 배수 검사 등에 주로 사용이 됩니다.
 나눗셈에서와 같이 피연산자가 정수형인 연산에서는 나누는 수(오른쪽 피연산자)로 0을 사용할 수 없고, 나머지 연산자 역시 0.0이나 0.0f로 나누는 것은 허용합니다.

public class Operator19
{

public static void main(String[] args) {

int portion = 10/8;
int remain = 10%8;
System.out.println("10을 8로 나누면,");
System.out.println("몫은 "+portion+"이고, 나머지는 " +remain+"입니다");

}
}

실행결과

10을 8로 나누면,
몫은 1이고, 나머지는 2입니다

public class Operator1 
{

public static void main(String[] args) {
for(int i=1; i<=10; i++){
if(i%3==0){
System.out.println(i);
}
}
}
}
실행결과

3
6
9

조건문과 반복문을 사용해서, 1과 10사이의 정수에서 3의 배수인 숫자만 출력하는 예제입니다. 반복문 for에서 i값을 1부터 10까지 1씩 증가시키면서 괄호{} 안의 문장들을 반복해서 수행합니다. 조건문 if는 조건이 만족하는 경우만 괄호{}안의 문장들을 수행합니다.  그래서 i%3의 결과가 0인 경우에만 i의 값을 화면에 출력합니다.

public class Operator20
{

public static void main(String[] args) {
System.out.println(-10%8);
System.out.println(10%-8);
System.out.println(-10%-8);
}
}

실행결과

-2
2
-2

피연산자 중에 음의 부호가 있는 경우에 어떤 결과를 얻는지 보여주는 예제이다. %연산자의 왼쪽에 있는 피연산자(나누어지는 수)의 부호에 따라 결정된다.
 피연산자(나누는 수)의 부호를 모두 무시하고 나머지 연산을 한 결과에 나눠지는 수의 부호를 붙이면 된다.




Java 연산자(산술연산자-사칙연산자)

3. 산술연산자

산술 연산자인 사칙 연산자(+ - * /), 나머지 연산자(%), 쉬프트 연산자(<<,>>,>>>)는 모두 두개의 피연산자를 취하는 이향 연산자입니다.
모든 이항 연산자는 연살을 수행하기 전에
 - 크기가 4byte이하인 자료형을 int형으로 변환한다.(byte, char, short -> int)
- 피연산자들의 타입을 서로 일치시킵니다.

3.1 사칙 연산자 + - * /

사칙 연산자는 프로그래밍에서 가장 많이 쓰이는 연사자 입니다. 보통 사람들이 이미 알고 있듯이 곱셈(*),나눗셈(/),나머지(%) 연산자가 덧셈(+),뺄셈(-)연산자 보다 우선수위가 높습니다.
1. int형(4byte)보다 크기가 작은 자료형은 int형으로 형변환 후에 연산을 수행합니다.
    byte + short -> int + int -> int
2. 두개의 피연산자 중 자료형의 표현범위가 큰 쪽에 맞춰서 형변환 후 수행합니다.
    int + float -> float + float -> float
3. 정수형 간의 나눗셈에서 0으로 나누는 것은 금지되어 있습니다.


ex)
byte + byte = int + int -> int
byte + short = int + int -> int
char + char = int + int -> int

float + int -> float + float -> float
long + float -> float + float -> float
float + double -> double + double -> double 

피연산자가 정수형인 경우, 나누는 수로 0을 사용할 수 없습니다. 만일 0으로 나누면, 컴파일은 정상적으로 되지만 실행 시 오류가 발생합니다. 하지만 부동소수점값인 0.0f, 0.0d로 나누는 것은 가능하지만 그 결과는 NaN(Not A Number, 숫자 아님)입니다.


public class Operator8 {

public static void main(String[] args) {
byte a = 10;
byte b = 20;
byte c = (byte) (a + b);
System.out.println(c);
}
}

실행결과


30

7번째 줄을 보면 형변환을 하였는데, a와 b는 int형보다 작은 byte형이기 때문에 연산자'+'는 이 두 개의 피연산자들의 자료형을 int형으로 변환한 다음 덧셈을 수행합니다. 그래서 'a+b'의 연산결과는 byte형이 아닌 int형이기 때문에 7번째 줄에 형변환을 꼭 붙여야 합니다. 그렇지 않으면 에러가 발생합니다.
크기가 작은 자료형의 값을 큰 자료형의 변수에 저장할 때는 자동으로 형변환되지만, 큰 자료형의 값을 작은 자료형 변수에 저장하려면 캐스트 연산자를 사용해서 변환해주어야 한다.
(주의) byte c = (byte)a+b;와 같이 문장을 써도 에러가 발생합니다. 그 이유는 형변환 연산자는 단항 연산자이므로 연산 순위가 이항 연산자인 덧셈 연산자보다 높습니다. 그렇기 때문에
(byte)a가 먼저 수행되고 다음 덧셈 연산이 수행됩니다. 즉 a만 byte형으로 형변환된 후 int형인 b와 연산을 합니다.

public class Operator9 {

public static void main(String[] args) {
byte a = 30;
byte b = 10;
byte c = (byte) (a*b);
System.out.println(c);
}
}

실행결과

44

이 예제를 실행하면 44가 화면에 출력되는데, 연산결과는 300이지만, 앞의 형변환에서 배웠듯이 큰 자료형에서 작은 자료형으로의 변환을 하면 데이터 손실이 발생하므로 원하는 결과값이 안나옵니다. 300은 byte의 범위를 넘기 때문에 byte형으로 변환하면 데이터 손실이 발생하여 44가 출력이 됩니다. byte형의 범위인 -128~127의 범위를 넘는 int형의 값을 byte형으로 변환하면, 원래의 값은 손실이 되고, byte형의 범위 중 한 값을 가지게 됩니다. 따라서 원하는 결과 값을 얻기 위해서는 충분히 큰 자료형을 사용해야합니다.

public class Operator10 {

public static void main(String[] args) {

int a = 1000000;
int b = 1000000;
long c = a * b;
System.out.println(c);


}
}

실행결과

-727379968

a*b의 결과를 long형 변수c에 저장하기 때문에 2*10^12를 저장하기에 충분하므로 '20000000000000'이 출력될 것 같지만, 결과는 예상과 다르게 나왔습니다. 이유는 int형과 int형의 연산결과는 int형이기 때문입니다. a*b의 결과가 이미 int형 값(-727379968)이기 때문에 long형으로 자동 변환이 되어서 long형 변수인 c에 저장되어도 결과는 같습니다. 따라서 원하는 값을 얻기 위해서는 변수 a, b의 타입을 long으로 바꾸어야 합니다.

public class Operator11 {

public static void main(String[] args) {

long a = 1000000 * 1000000;
long b = 1000000 * 1000000L;

System.out.println(a);
System.out.println(b);

}
}

실행결과

-727379968
1000000000000

1000000 * 1000000은 int와 int의 연산이기 때문에 그 결과가 int입니다. 그래서 10^6*10^6의 곱셈연산은 10^12이기 때문에 int의 최대값인 대략 2*10^9을 넘기 때문에 오버플로우가 발생해서 -727379968를 결과로 얻습니다.
1000000 * 1000000L은 int와 long의 연산이기 때문에 그 결과가 long입니다. long은 10^12을 저장하기에는 충분한 자료형이므로 원하는 결과를 얻을 수 있습니다.


public class Operator12 {

public static void main(String[] args) {

long a = 1000000 * 1000000 / 1000000;
long b = 1000000 / 1000000 * 1000000;

System.out.println(a);
System.out.println(b);

}
}

실행결과

-727
1000000

곱셉 연산을 먼저 하면 int의 범위를 넘어서기 때문에 워하는 결과가 나오지 않습니다.
위와 같이 곱셈과 나눗셈의 연산 중에 무엇을 먼저 쓰느냐에 따라서 결과가 달르게 나옵니다. 

public class Operator13 {

public static void main(String[] args) {

char ch1 = 'a';
char ch2 = ch1;
char ch3 = ' ';

int i = ch1 + 1;

ch3 = (char)(ch1+1);
ch2++;
ch2++;

System.out.println("i="+i);
System.out.println("ch2="+ch2);
System.out.println("ch3="+ch3);

}
}

실행결과

i=98
ch2=c
ch3=b

ch1을 계산할 때, ch1이 char형이므로 int형으로 변환한 후 덧셈연산을 수행하게 되기 때문에 c1에 저장되어 잇는 코드값이 변환되어 int형 값이 된다. 따라서 ch1+1은 97+1이 되어 int형 변수 i에는 98이 저장이 됩니다.
ch2++은 형변환없이 ch2에 저장되어 있는 값을 1 증가시키므로, 예제에서는 원래 저장되어 있던 값인 97을 1씩 두 번 증가하여 99가 됩니다. 코드값이 10진수로 99인 문자는 'c'이므로 c2를 출력하면 c가 출력됩니다.


public class Operator14 {

public static void main(String[] args) {


char ch1 = 'a';
// char ch2 = ch1+a;  //컴파일 에러 발생
char ch2 = 'a'+1;       //컴파일 에러 없음

System.out.println(ch2);

}
}

실행결과

b

덧셈 연사자와 같은 이항 연산자는 int보다 작은 타입의 피연사자를 int로 자동형변환한도 했는데 왜 에러가 발생하지 않는 것일까?
'a+1'이 리터널 간의 연산이기 때문이다. 상수 또는 리터널 간의 연산은 실행과정동안 변한느 값이 아니기 때문에, 컴파일 할때 컴파일러가 계산해서 그 결과로 대체함으로써 코드를 보다 효율적으로 만든다.
컴파일러가 미리 덧셈연산을 수행하기 때문에 실행 시에는 덧셈 연산이 수행되징 ㅏㄶ는다. 그저 덧셈연산결과인 문자 b를 ch2에 저장한다.

컴파일 전의 코드               컴파일 후의 코드
char ch2 = 'a'+1'              char ch2 = 'b';
int a = 60*60*60;              int a = 216000;

하지만 에러가 발생하는 부분은 수식에 변수가 들어가 있다. 변수가 들어가 있는 경우에는 컴파일러가 미리 계산을 할 수 없기 때문에 아래의 오른쪽 코드와 같이 형변화을 해주어야 한다.
즉 char ch2 = c1 + 1; -> char ch2 = (char)(c1 + 1);

public class Operator15 {

public static void main(String[] args) {

char ch = 'a';
for(int i=0; i<26; i++){       //출력() 안의 문장을 26번 반복한다.
System.out.print(ch++);   //'a'부터 26개의 문자를 출력한다.
}
System.out.println();         //줄바꿈
ch = 'A';
for(int i=0;i<26;i++){
System.out.print(ch++);
}
System.out.println(); 
ch = '0';
for(int i=0;i<10;i++){
System.out.print(ch++);
}
System.out.println(); 
}
}

실행결과

abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789

문자 a부터 z까지 26개의 문자를 출력하고, 문자A부터 Z까지 26개의 문자를 출력하며, 0부터 9까지 10개의 숫자를 출력합니다. 문자 a의 코드값은 10진수로 97, b의 코드값은 98.... z의 코드값은 122입니다. 문자 A의 코드값은 10진수로 65...Z의 코드값은 90입니다. 그리고 문자 0의 코드값은 48입니다.
이를 이용하여 대문자를 소문자로, 소문자를 대문자로 변환하는 프로그램을 작성할 수 있습니다.

public class Operator1 {

public static void main(String[] args) {
char ch1 = 'a';
char ch2 = (char)(ch1 - 32);
System.out.println(ch2);
}
}

실행결과

A


a의 코드값이 97이고, A의 코드값이 65입니다. a보다 32가 적으므로 소문자 a의 코드값에서 32를 빼면 대문자 A가 출력되고, 반대로 A의 코드값에 32를 더하면 소문자 a가 출력이 됩니다.

public class Operator18 
{

public static void main(String[] args) {
float Pi = 3.141592f;
float intPi = (int)(Pi*1000)/1000f;
System.out.println(intPi);
}
}

실행결과

3.141

int형 간의 나눗셈 int/int를 수행하면 float나 double이 아닌 int다. 그리고 나눗셈의 결과는 반올림이 아니라 버린다. 1/2의 결과는 1.5가 아니라 1이다.
위의 예제는 누눗셈 연산자의 성지을 이용해서 실수형 변수 pi의 값을 소수점을 셋째자리가지만 빼내는 방법을 보여준다.
(int)(pi * 1000)/1000f;에서 (pi*1000)이 먼저 수행이 된다. pi는 float, 1000은 정수형이기 때문에 연산 결과는 float형인 3.141.592f가 됩니다.
(int)(3141.592f)/1000f에서 단항연산자인 캐스트연산자의 형변환이 수행됩니다. 3141.592f를 int로 변환하면 3141을 얻게 됩니다. 소수점 이하의 자리는 반올림 없이 버려집니다.
3141/1000f;에서 int와 float의 연산이므로 int가 float로 변환된 다음, float/float의 연산이 수행됩니다. float와 float의 연산이므로, float인 3.141f가 출력됩니다.






Java 연산자(비트전환 연산자와 논리부정 연산자)

2.3 비트전환 연산자 ~


비트전환 연산자'~'는 정수형과 char형에서만 사용이 되며, 피연산자를 2진수로 표현 했을 때, 0은 1로 1은 0으로 바꾼다. 그래서 연산자 '~'에 의해 비트전환이 되면 피연산자의 부호가 반대로 변경된다.
(byte, short, char형은 int형으로 변경된 후 전환된다)

2진수                  10진수
0/0/0/0/0/0/0/0      +10
1/1/1/1/1/1/1/1      -11

public class operarot5 {

public static void main(String[] args) {

byte b = 10;
System.out.println("b="+b);
System.out.println("~b="+~b);
System.out.println("~b+1="+(~b+1));
}

}

실행결과

b=10
~b=-11
~b+1=-10

결과를 보면, 어떤 양의 정수에 대한 음의 정수를 얻으려면 어떻게 해야하는지 알 수 있습니다. 양의 정수 b가 있을 때, b에 대한 음의 정수를 얻으려면 ~b+1을 계산하면 됩니다.

      2진수                     10진수         
0/0/0/0/1/0/1/0                 10
1/1/1/1/0/1/0/1                -11
1/1/1/1/0/1/0/1                -11
0/0/0/0/0/0/0/1          +)     1
1/1/1/1/0/1/1/0                -10

먼저 10을 2진수로 표현한 다음 0을 1로, 1을 0으로 바꾸고 그 결과에 1을 더하면 -10의 2진 표현을 얻을 수 있다.


public class Operator6 {

public static void main(String[] args) {
byte a = 10;
byte result = (byte) ~a;
System.out.println("a = "+a);
System.out.println("result = "+result);
}
}

실행결과


a = 10
result = -11

연산자 ~는 피연산자 타입이 int보다 작으면, int형으로 변환 후 연산을 수행하기 때문에 위의 예제에서 byte형 변수 a를 int형으로 변환 후 연산을 수행하기 때문에 연산결과를 저장하기 위해서는 int형 변수에 저장하거나, 캐스트 연산자를 사용해야합니다.

2.4 논리부정 연산자 !

이 연산자는 boolean형에만 사용할 수 있으며, true는 false로 false는 true로 변경합니다.
존건문과 반복문의 조건식에 사용되어 조건식을 보다 효율적으로 만들어 줍니다. 연산자 !를 이용해서 한번 누르면 on, 또 한번 누르면 off가 되는 토글버튼을 논리적으로 구현할 수 있습니다.

public class Operator7 {

public static void main(String[] args) {
boolean power = true;
System.out.println(power);
power = !power;
System.out.println(power);
power = !power;
System.out.println(power);
}
}

실행결과

true
false
true