Posts 🍡 λΆ€λ™μ†Œμˆ˜μ μ˜ μ“°λ ˆκΈ°κ°’ μ²˜λ¦¬ν•˜κΈ°
Post
Cancel

🍡 λΆ€λ™μ†Œμˆ˜μ μ˜ μ“°λ ˆκΈ°κ°’ μ²˜λ¦¬ν•˜κΈ°

λΆ€λ™μ†Œμˆ˜μ μ˜ κ·Ήμ†Œμˆ˜κ°’

μ‹€μ œλ‘œ λΆ€λ™μ†Œμˆ˜μ (μ‹€μˆ˜) 연산을 λ‹€λ£¨λŠ” 것은 μ‰½μ§€λ§Œ, μ»΄ν“¨ν„°μ˜ λΆ€λ™μ†Œμˆ˜μ  μ—°μ‚° μ²˜λ¦¬λŠ” μ‰½μ§€λ§Œμ€ μ•Šλ‹€. μ»΄ν“¨ν„°μ—μ„œ 값은 2μ§„μˆ˜λ‘œ 닀루고, 이 λ•Œλ¬Έμ— 컴퓨터가 λΆ€λ™μ†Œμˆ˜μ  값을 μ—°μ‚°ν•  λ•Œ IEEE 754 λͺ…세에 따라 μž‘μ—…μ„ μˆ˜ν–‰ν•œλ‹€. 이 과정에 κ°’μ˜ μ™œκ³‘μ΄ λ°œμƒν•  수 μžˆλ‹€. 이 λ¬Έμ œλŠ” CPUλ‚˜ OS, JVM의 λ¬Έμ œκ°€ μ•„λ‹ˆλΌ λͺ…세에 따라 λΆ€λ™μ†Œμˆ˜μ μ„ μ²˜λ¦¬ν•˜λŠ” λͺ¨λ“  μ»΄ν“¨ν„°μ—μ„œ λ°œμƒν•˜λŠ” λ¬Έμ œμ΄λ‹€.

λ”°λΌμ„œ λΆ€λ™μ†Œμˆ˜μ μ€ λΉ„κ΅μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜μ—¬ 비ꡐ할 λ•Œ, λΆ€λ™μ†Œμˆ˜μ μ˜ 값을 비ꡐ할 λ•Œ IEEE 754 λ³€ν™˜ 곡식에 따라 λ°œμƒν•˜λŠ” μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œλŠ” κ·Ήμ†Œμˆ˜κ°’μ„ μ²˜λ¦¬ν•΄μ£ΌλŠ” μ½”λ“œκ°€ λ”°λ‘œ ν•„μš”ν•˜λ‹€. 비ꡐ연산을 ν•  λ•Œ, ν”Όμ—°μ‚°μžμ˜ μ˜€μ°¨κ°€ μ˜€μ°¨λ²”μœ„λ³΄λ‹€ μž‘λ‹€λ©΄ 같은 κ°’μœΌλ‘œ μ·¨κΈ‰ν•΄μ£ΌλŠ” 것이 κ·Έ 방법이닀.

κ·Ήμ†Œμˆ˜κ°’ 처리 방법

@직접 μ˜€μ°¨λ²”μœ„ 지정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
double d1 = 987.6543;
double d2 = 1.111111;
System.out.println(d1 + d2 == 988.765411);	// false
System.out.println(d1 + d2);				// 988.7654110000001
// κ²°κ³Ό 뒀에 κ·Ήμ†Œμˆ˜μ˜ 값이 λΆ™λŠ”λ‹€.

double x = 234.765411;
double y = 754.0;
System.out.println(x + y == 988.765411);	// true
System.out.println(x + y);					// 988.765411
// κ²°κ³Ό 뒀에 κ·Ήμ†Œμˆ˜μ˜ 값이 뢙지 μ•Šμ•˜λ‹€.

System.out.println(d1 + d2 == x + y); 		// false

//-------------------------------------------
double EPSILON = 0.00001;
System.out.println(Math.abs(d1 + d2 - (x + y)) < EPSILON);		//true

μœ„μ˜ μ½”λ“œμ—μ„œ d1 + d2μ—λŠ” κ·Ήμ†Œμˆ˜μ˜ 값이 λΆ™κ³ , x + yμ—λŠ” 뒀에 κ·Ήμ†Œμˆ˜μ˜ 값이 뢙지 μ•Šμ•˜λ‹€. λ”°λΌμ„œ 같은 값이 λ‚˜μ™€μ•Ό 함에도 λΆˆκ΅¬ν•˜κ³  κ·Ήμ†Œμˆ˜μ˜ κ°’ λ•Œλ¬Έμ— λΉ„κ΅μ—°μ‚°μžλ₯Ό μ‚¬μš©ν–ˆμ„ λ•Œ falseκ°€ λ‚˜μ˜€κ²Œ λ˜μ—ˆλ‹€.

μ•„λž˜μ˜ 두 쀄을 μ„€λͺ…ν•˜μžλ©΄

  1. EPSILON 값을 μ„ μ–Έν•œλ‹€.
  2. 각각 μ—°μ‚°μ—μ„œ κ³„μ‚°ν•œ κ°’μ˜ 였차λ₯Ό κ΅¬ν•œλ‹€.
  3. Math.abs() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ˜€μ°¨μ— μ ˆλŒ€κ°’μ„ κ΅¬ν•œλ‹€.
  4. 이 였차의 μ ˆλŒ€κ°’μ΄ EPSILON보닀 μž‘λ‹€λ©΄ 두 결과값을 같은 κ°’μœΌλ‘œ μ·¨κΈ‰ν•œλ‹€.

μ ˆλŒ€κ°’μœΌλ‘œ λ°”κΏ”μ£ΌλŠ” 이유

=> 음수의 경우 무쑰건 EPSILON 값보닀 μž‘λ‹€. λ”°λΌμ„œ μ ˆλŒ€κ°’μ„ 쓰지 μ•ŠλŠ”λ‹€λ©΄ 음수의 경우 -EPSILON 보닀 μž‘μ•„μ•Ό ν•œλ‹€λŠ” 쑰건을 μ€‘λ³΅ν•΄μ„œ μ½”λ”©ν•΄μ•Ό 함

@ INFINITY κ°’ μ‚¬μš©

1
2
3
4
5
6
7
8
float f1 = 0.1f;
float f2 = 0.1f;

System.out.println(f1 * f2 == 0.01f); // false
System.out.println(f1 * f2); // 0.010000001

float r = f1 * f2 - 0.01f;
System.out.println(Math.abs(r) <= Float.POSITIVE_INFINITY);

μœ„μ˜ μ½”λ“œμ—μ„œλŠ” 직접 μ˜€μ°¨λ²”μœ„λ₯Ό μ •ν•˜μ§€ μ•Šκ³  μžλ°”μ— μ •μ˜λœ Float.POSITIVE_INFINITY 값을 μ˜€μ°¨λ²”μœ„λ‘œ μ‚¬μš©ν•˜μ˜€λ‹€.

This post is licensed under CC BY 4.0 by the author.

학원 #11일차: λ°°μ—΄, μΈμŠ€ν„΄μŠ€μ™€ 레퍼런슀, 가비지

학원 #12일차: μ‚°μˆ μ—°μ‚°μžμ™€ ν˜•λ³€ν™˜

Loading comments from Disqus ...