[Java] Overflow & Underflow, Type Conversion

zxcevΒ·2023λ…„ 3μ›” 5일
0

Java

λͺ©λ‘ 보기
2/3
post-thumbnail

πŸ’‘ λͺ¨λ“  μ½”λ“œλŠ” μ•„λž˜ λ§ν¬μ—μ„œ 직접 μ‹€ν–‰ν•΄ λ³Ό 수 μžˆλ‹€.
https://www.sololearn.com/compiler-playground/java

Decimal Types in Java

Javaμ—λŠ” byte, short, int, long의 4가지 μ •μˆ˜ νƒ€μž…μ΄ μ‘΄μž¬ν•œλ‹€.

μ‹€μˆ˜ νƒ€μž…(number) ν•˜λ‚˜λ‘œ λͺ¨λ“  숫자λ₯Ό ν‘œν˜„ν•˜λŠ” JavaScriptλ³΄λ‹€λŠ” 많고,
λΆ€ν˜Έ μ—†λŠ” μ •μˆ˜(unsigned int)κΉŒμ§€ μ‘΄μž¬ν•˜λŠ” Goλ³΄λ‹€λŠ” 적닀.

각 νƒ€μž…μ€ μˆœμ„œλŒ€λ‘œ 1, 2, 4, 8 byte의 λ©”λͺ¨λ¦¬ 곡간을 μ°¨μ§€ν•œλ‹€.

πŸ’‘ 사싀 charμ΄λΌλŠ” 2byte μ •μˆ˜ νƒ€μž…μ΄ ν•˜λ‚˜ 더 μ‘΄μž¬ν•œλ‹€.
μ΄λŠ” 단일 μœ λ‹ˆμ½”λ“œ 문자λ₯Ό ν‘œν˜„ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λ©°, ν¬κΈ°λŠ” short와 κ°™μ§€λ§Œ,
Javaμ—μ„œ μœ μΌν•˜κ²Œ λΆ€ν˜Έ μ—†λŠ” μ •μˆ˜ νƒ€μž…μ΄κΈ° λ•Œλ¬Έμ— short와 같은 byte ν¬κΈ°μž„μ—λ„ λΆˆκ΅¬ν•˜κ³ 
νƒ€μž… λ³€ν™˜μ΄ λΆˆκ°€ν•˜λ‹€.
λΆ€ν˜Έμ˜ 유무 λ•Œλ¬Έμ— shortλŠ” -32,768 ~ 32,767, char은 0 ~ 65,535둜
λ‹€λ₯Έ λ²”μœ„λ₯Ό κ°–κ³ , 같은 λΉ„νŠΈνŒ¨ν„΄μ΄μ–΄λ„ λ‹€λ₯Έ 수λ₯Ό κ°€λ¦¬ν‚€κ²Œ 되기 λ•Œλ¬Έμ΄λ‹€.

1byteλŠ” 8bit이기 λ•Œλ¬Έμ— μ΄μ§„μˆ˜λ‘œ 2^8κΉŒμ§€ ν‘œν˜„μ΄ κ°€λŠ₯ν•˜λ‹€.
byte νƒ€μž…μ€ 1byteμ΄λ―€λ‘œ 2^8인 256가지 경우의 수λ₯Ό ν‘œν˜„ν•  수 있고,
shortλŠ” 2byteμ΄λ―€λ‘œ 2^16인 65,535가지 경우의 수λ₯Ό ν‘œν˜„ν•  수 μžˆλ‹€.
같은 μ›λ¦¬λ‘œ intλŠ” 4,294,967,296가지,
long은 18,446,744,073,709,551,616가지 경우의 수λ₯Ό ν‘œν˜„ν•  수 μžˆλ‹€.

Overflow

κ·Έλ ‡λ‹€λ©΄ λ§Œμ•½ 각 νƒ€μž…μ˜ λ²”μœ„λ₯Ό λ„˜μ–΄μ„œλŠ” 수λ₯Ό λ„£μœΌλ©΄ μ–΄λ–»κ²Œ 될까.

public class Program
{
    public static void main(String[] args) {
		byte b1 = 127;
        byte b2 = 128; // Incompatible types. Found: 'int', required: 'byte'
        System.out.println(b1);
		System.out.println(b2);
	}
}

였λ₯˜κ°€ λ°œμƒν•œλ‹€.
기본적으둜 μ •μˆ˜ λ¦¬ν„°λŸ΄μ€ 4byte인 int둜 μΈμ‹ν•˜λŠ”λ°,
byte νƒ€μž… λ³€μˆ˜μ˜ λ²”μœ„λŠ” -128 ~ 127이기 λ•Œλ¬Έμ— 이 λ²”μœ„ μ•ˆμ˜ μ •μˆ˜ λ¦¬ν„°λŸ΄μ„
byte νƒ€μž…μ˜ λ³€μˆ˜μ— λŒ€μž…ν•˜λ©΄ μžλ™ ν˜•λ³€ν™˜μ„ ν•΄μ£ΌκΈ° λ•Œλ¬Έμ— μ •μƒμ μœΌλ‘œ λ™μž‘ν•˜μ§€λ§Œ,
이 λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜λŠ” 값은 μžλ™μœΌλ‘œ ν˜•λ³€ν™˜ν•˜μ§€ μ•Šκ³  였λ₯˜λ₯Ό λ°œμƒμ‹œν‚¨λ‹€.

public class Program
{
    public static void main(String[] args) {
		byte b1 = 127;
        byte b2 = (byte) 128;
        System.out.println(b1); // -128
		System.out.println(b2);
	}
}

byte λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜λŠ” μ •μˆ˜ λ¦¬ν„°λŸ΄μ„ byte νƒ€μž… λ³€μˆ˜μ— ν• λ‹Ήν•˜κ³  μ‹Άλ‹€λ©΄,
μœ„μ™€ 같이 λͺ…μ‹œμ μœΌλ‘œ νƒ€μž… λ³€ν™˜μ„ ν•΄μ£Όλ©΄ λœλ‹€.

그런데 127에 1이 μΆ”κ°€λœ 128을 λŒ€μž…ν–ˆλŠ”λ°, κ²°κ³ΌλŠ” -128이 λ‚˜μ˜¨λ‹€.
이유인 μ¦‰μŠ¨, byte λ²”μœ„μ˜ μ΅œλŒ“κ°’μ€ 127이고, 거기에 1을 λ”ν•˜λ©΄ λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜κΈ° λ•Œλ¬Έμ—
μ΅œμ†Ÿκ°’μΈ -128둜 λŒμ•„κ°€κ²Œ λ˜λŠ” 것이닀.
이λ₯Ό Overflow라고 λΆ€λ₯Έλ‹€.
νƒ€μž…μ΄ κ°€μ§ˆ 수 μžˆλŠ” μ΅œλŒ“κ°’μ„ λ„˜μ–΄κ°€μ„œ λ‹€μ‹œ μ΅œμ†Ÿκ°’μ΄ 된 것이닀.

Underflow

λ°˜λŒ€λ‘œ UnderflowλŠ” νƒ€μž…μ΄ κ°€μ§ˆ 수 μžˆλŠ” μ΅œμ†Ÿκ°’λ³΄λ‹€ λ°‘μœΌλ‘œ λ‚΄λ €κ°€μ„œ λ‹€μ‹œ μ΅œλŒ“κ°’μ΄ λ˜λŠ” 것이닀.

public class Program
{
    public static void main(String[] args) {
		byte b1 = -128;
        byte b2 = (byte) -129;
        System.out.println(b1); // 127
		System.out.println(b2);
	}
}

μ•„λ‚ λ‘œκ·Έ μ‹œκ³„λ₯Ό μƒκ°ν•˜λ©΄ λœλ‹€.

12μ‹œμ—μ„œ 1μ‹œκ°„μ„ λ”ν•˜λ©΄ 13μ‹œκ°€ μ•„λ‹Œ 1μ‹œκ°€ 되고,
1μ‹œμ—μ„œ 1μ‹œκ°„μ„ λΉΌλ©΄ 0μ‹œκ°€ μ•„λ‹Œ 12μ‹œκ°€ λ˜λŠ” 것과 μœ μ‚¬ν•˜λ‹€.

Implicit Type Conversion(Promotion)

byte νƒ€μž…μ€ μ‹€μ œλ‘œ λ©”λͺ¨λ¦¬ μƒμ—μ„œ 8μΉΈ 짜리 byte 배열이라고 μƒκ°ν•˜λ©΄ λœλ‹€.
[0, 0, 0, 0, 0, 0, 0, 0]κ³Ό 같은 ν˜•νƒœμΌ 것이닀.
이λ₯Ό κ°„κ²°ν•˜κ²Œ 00000000으둜 ν‘œκΈ°ν•˜κ² λ‹€.

shortλŠ” 2byte ν¬κΈ°μ΄λ―€λ‘œ 00000000 00000000κ³Ό 같은 ν˜•νƒœμΌ 것이닀.

κ·Έλ ‡λ‹€λ©΄ 더 적은 λ©”λͺ¨λ¦¬ 곡간을 κ°–λŠ” byteλ₯Ό short둜 λ³€ν™˜ν•˜λ©΄ μ–΄λ–»κ²Œ 될까.

11을 μ΄μ§„μˆ˜λ‘œ λ‚˜νƒ€λ‚΄λ©΄ 00001011이닀.
κ·Έλž˜μ„œ byte νƒ€μž…μ— 11을 μ €μž₯ν•˜λ©΄ μ‹€μ œλ‘œλŠ” 00001011이 λ©”λͺ¨λ¦¬μ— μ €μž₯될 것이닀.

이λ₯Ό short νƒ€μž…μœΌλ‘œ λ³€ν™˜ν•˜λ©΄ μ•žμ— 00000000을 ν•˜λ‚˜ 더 λΆ™μ—¬μ£Όλ©΄ λœλ‹€.
00001011 -> 00000000 00001011이 λ˜λŠ” 것이닀.

μœ„μ²˜λŸΌ 더 μž‘μ€ νƒ€μž…μ„ 더 큰 νƒ€μž…μœΌλ‘œ λ³€ν™˜ν•˜λŠ”λ°λŠ” μ•„λ¬΄λŸ° λ¬Έμ œκ°€ μ—†λ‹€.
κ·Έλž˜μ„œ JavaλŠ” 이런 경우 μžλ™μœΌλ‘œ νƒ€μž… λ³€ν™˜μ„ ν•΄μ€€λ‹€.

κ·Έλž˜μ„œ 이λ₯Ό Implicit Type Converion(μ•”μ‹œμ  ν˜•λ³€ν™˜)이라고 λΆ€λ₯Έλ‹€.

μ½”λ“œλ‘œ 직접 μ‹€ν–‰ν•˜λ©° ν™•μΈν•΄λ³΄μž.

public class Program
{
    public static void main(String[] args) {
		byte b = 11;
        short s = b;
        System.out.println(s); // 11
	}
}

short νƒ€μž… λ³€μˆ˜μ— byte νƒ€μž…μ˜ 값을 넣어도 아무 문제 없이 11이 좜λ ₯λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€.

public class Program
{
    public static void main(String[] args) {
		short s = 1;
        char c = s; // java: incompatible types: possible lossy conversion from short to char
	}
}

단, char νƒ€μž…μ€ short와 λ§ˆμ°¬κ°€μ§€λ‘œ 2byte의 크기λ₯Ό 가짐에도 λΆˆκ΅¬ν•˜κ³  ν˜•λ³€ν™˜μ΄ λΆˆκ°€λŠ₯ν•˜λ‹€.
μ•žμ„œ μ‚΄νŽ΄λ΄€λ“― charκ°€ μ• μ΄ˆμ— 음수 λ²”μœ„λ₯Ό ν¬ν•¨ν•˜μ§€ μ•ŠλŠ” Unsigned νƒ€μž…μ΄κΈ° λ•Œλ¬Έμ—,
0 ~ 65,535의 λ²”μœ„λ₯Ό κ°€μ Έμ„œ 같은 λΉ„νŠΈνŒ¨ν„΄μ΄μ–΄λ„ μ „ν˜€ λ‹€λ₯Έ 수λ₯Ό 가리킀기 λ•Œλ¬Έμ΄λ‹€.

Explicit Type Conversion(Type Casting)

μ•„κΉŒμ™€ λ°˜λŒ€λ‘œ μ΄λ²ˆμ—λŠ” 더 큰 short νƒ€μž…μ„ 더 μž‘μ€ byte νƒ€μž… λ³€μˆ˜μ— ν• λ‹Ήν•΄λ³΄μž.

public class Program
{
    public static void main(String[] args) {
		short s = 1;
        byte b = s; // java: incompatible types: possible lossy conversion from short to byte
	}
}

possible lossy conversionμ΄λΌλŠ” 였λ₯˜κ°€ 보인닀.

νƒ€μž… λ³€ν™˜μœΌλ‘œ 인해 데이터가 μœ μ‹€λ  κ°€λŠ₯성이 μžˆλ‹€λŠ” λœ»μ΄λ‹€.

μœ„ μ½”λ“œμ—μ„œ short νƒ€μž… λ³€μˆ˜ s의 λΉ„νŠΈνŒ¨ν„΄μ€ 00000000 00000001일 것이닀.
λ§Œμ•½ μ½”λ“œκ°€ μ •μƒμ μœΌλ‘œ μ‹€ν–‰λœλ‹€λ©΄ byteλŠ” 8bitμ΄λ―€λ‘œ
λ’·λΆ€λΆ„μ˜ λΉ„νŠΈνŒ¨ν„΄λ§Œ κ°€μ Έμ˜¬ 것이고 00000001이 할당될 것이닀.

μœ„ μΌ€μ΄μŠ€μ—μ„œλŠ” μ†μ‹€λ˜λŠ” 데이터가 μ „ν˜€ μ—†λ‹€.

κ·ΈλŸ¬λ‚˜ sκ°€ λ§Œμ•½ 00001111 00000001μ΄μ—ˆλ‹€λ©΄?

μ•žμ˜ 00001111은 byte νƒ€μž…μ˜ λ³€μˆ˜μ— 담을 수 μ—†λ‹€.
이 κ²½μš°μ—λ„ λ§ˆμ°¬κ°€μ§€λ‘œ 00000001만 μ €μž₯λ˜μ–΄ 1이 될 것이닀.

κ·Έλž˜μ„œ 데이터가 μœ μ‹€λ  κ°€λŠ₯성이 μžˆλ‹€λŠ” 였λ₯˜κ°€ λ‚˜νƒ€λ‚œ 것이닀.

κ²½μš°μ— 따라 λ‹€λ₯΄κ² μ§€λ§Œ μ‹€μ œ μ„œλΉ„μŠ€μ—μ„œ 이런 데이터 μœ μ‹€μ΄ λ°œμƒν•œλ‹€λ©΄, κ±°λŒ€ν•œ 였λ₯˜λ₯Ό μ΄ˆλž˜ν•  수 μžˆλ‹€.

κ³„μ’Œ μ΄μ²΄λ‚˜ λ‘œμΌ“ ꢀ도λ₯Ό κ³„μ‚°ν•˜λŠ” λ“±μ˜ μ•„μ£Ό λ―Όκ°ν•œ μž‘μ—…μ—μ„œλŠ”
μž‘μ€ λ°μ΄ν„°μ˜ 손싀이 λŒμ΄ν‚¬ 수 μ—†λŠ” κ²°κ³Όλ₯Ό λ‚³κΈ° λ•Œλ¬Έμ΄λ‹€.

κ·Έλž˜μ„œ μ΄λŸ¬ν•œ 였λ₯˜λ₯Ό 사전 μ˜ˆλ°©ν•˜κΈ° μœ„ν•΄μ„œ ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰ν•˜κΈ° 전인 컴파일 νƒ€μž„μ— 미리 μ•Œλ €μ£ΌλŠ” 것이고,
λ§Œμ•½ κ°œλ°œμžκ°€ μ΄λŸ¬ν•œ 데이터 μœ μ‹€ κ°€λŠ₯성을 μ•Œκ³  μžˆμŒμ—λ„ λΆˆκ΅¬ν•˜κ³ , μ™„λ²½νžˆ 수의 λ²”μœ„λ₯Ό μ»¨νŠΈλ‘€ν•΄μ„œ 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚€μ§€ μ•Šμ„ μžμ‹ μ΄ μžˆλ‹€λ©΄, κ·Έ λ•Œ νƒ€μž… λ³€ν™˜μ„ λͺ…μ‹œν•˜λ©΄ μ œλŒ€λ‘œ μž‘λ™ν•  것이닀.

public class Program
{
    public static void main(String[] args) {
		short s = 1;
        byte b = (byte) s;
        System.out.println(b); // 1
	}
}

λ°”λ‘œ μœ„μ™€ 같은 κ²½μš°λ‹€.
1이 short에 λ‹΄κΈ°λ©΄ λΉ„νŠΈνŒ¨ν„΄μ€ 00000000 00000001이닀.
이 쀑 첫번째 byteκ°€ 00000000μ΄λ―€λ‘œ μ•„λ¬΄λŸ° 데이터가 λ‹΄κ²¨μžˆμ§€ μ•Šλ‹€λŠ” 것을 μš°λ¦¬λŠ” ν™•μ‹€νžˆ μ•Œκ³  μžˆλ‹€.

κ·Έλž˜μ„œ λ‘λ²ˆμ§Έ byte만 byte νƒ€μž… λ³€μˆ˜ b에 담을 것이고, 이 κ³Όμ •μ—μ„œ μ–΄λ– ν•œ 데이터 손싀도 μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€.
(byte) s와 같이 λ³€ν™˜ν•  νƒ€μž…μ„ 직접 λͺ…μ‹œν•΄μ„œ κ°•μ œλ‘œ νƒ€μž…μ„ λ³€ν™˜ν•˜λŠ” 것을 νƒ€μž… μΊμŠ€νŒ…μ΄λΌκ³  λΆ€λ₯΄λ©°,
이에 λ”°λ₯Έ 였λ₯˜ λ°œμƒ λ“±μ˜ μ±…μž„μ€ μ˜¨μ „νžˆ κ°œλ°œμžμ—κ²Œ 있기 λ•Œλ¬Έμ— μ‚¬μš©ν•  λ•Œ 항상 μ£Όμ˜ν•΄μ•Ό ν•œλ‹€.

0개의 λŒ“κΈ€