Java Category/Java

[JAVA] 기본 연산을 할 때 주의사항

ReBugs 2023. 7. 12.

리터럴

기본적으로 컴파일러는 정수 리터럴을 int타입으로 간주한다는 점이다.

따라서 int타입의 허용범위를 초과할 경우 long 타입임을 컴파일러에게 알려줘야 한다.

컴파일러에게 long타입임을 알려주는 방법은 정수 리터럴 뒤에 소문자 l이나 대문자 L을 붙이면 된다.

long a = 10000000000; //컴파일 에러
long b = 10000000000L; //정상

또한 실수 리터럴을 기본적으로 double 타입으로 해석하기 때문에, 실수 리터럴을 float타입으로 저장하고 싶다면 리터럴 뒤에 소문자 f나 대문자 F를 붙여 컴파일러가 float 타입임을 알 수 있도록 해야 함

float a = 3.14; //컴파일 에러
float b = 3.14F; // 정상

 


 

컴파일 단계 연산과 JVM 연산

자바는 컴파일 단계 연산과 JVM 연산이 있다.

컴파일 단계 연산은 리터럴끼리 연산을 하게 된다면 컴파일러가 먼저 연산을 하게 되지만, 변수가 하나라도 끼게 된다면, JVM이 연산을 하게 된다.

byte b1 = 1 + 1; //컴파일 단계에서 연산
byte b2 = 1;
byte b3 = b2 + 1; // JVM에서 연산하므로 우변이 int로 바뀌면서 오버 플로
byte b3 = (byte) (b2 + 1); //올바른 코딩

 

byte b1 = 1 + 1; //컴파일 단계에서 연산

이 코드는 컴파일 단계에서 2로 처리한 다음 JVM에게 넘겨준다.

byte b3 = b2 + 1; // JVM에서 연산하므로 우변이 int로 바뀌면서 오버 플로

이 코드는 컴파일러가 연산하지 않고 JVM에서 연산하게 되어서 오류가 발생한다.

 


 

정확한 계산은 정수 연산으로

int apple = 1;
double pieceJnit = 0.1;
int number = 7;

double result = apple - pieceJnit*number;
System.out.println(result); //0.3이 아닌 2.9999999

위 코드와 같이 부동 소수점 방식을 사용하는 실수 타입에서는 정확한 값이 나오지 않는다.

그렇기 때문에 정확한 계산이 필요하다면 정수 연산으로 변경해서 아래와 같이 계산하는 것이 좋다.

int apple = 1;
int totalPrice = apple * 10;
int number = 7;
int result = totalPrice - number;
System.out.println(result/10.0); //0.3

 


 

나눗셈 연산 후 NaN과 Infinity 처리

나눗셈 또는 나머지 연산에서 좌측 피연산자가 정수이고 우측 피연산자가 0일 경우 예외가 발생한다.

무한대의 값을 정수로 표현할 수 없기 때문이다.

int x = 5;
int y = 0;
int result = 5 / 0; //예외 발생

하지만 좌측 피연산자가 실수이거나 우측 피연산자가 0.0 또는 0.0f이면 예외가 발생하지 않고 연산의 결과는 Infinity 또는 NaN(Not a Number)이 된다.

즉, 5 / 0.0 은 Infinity가 나오고, 5 % 0.0은 NaN이 나온다.

Infinity 또는 NaN 상태에서 계속해서 연산을 수행하면 안 된다. 어떤 연산을 하더라도 결과는 계속해서 Infinity와 NaN이 되므로 데이터가 엉망이 될 수 있다.

따라서 Infinity 또는 NaN인지 먼저 확인하고 다음 연산을 수행하는 것이 좋다.

int x = 5;
double y = 0.0;
double z = x / y;
if(Double.isInfinite(z) || Double.isNaN(z)) System.out.println("잘못된 값이므로 연산을 할 수 없습니다.");
else System.out.println("다음 연산을 실행");

댓글