[기초] 부동소수점의 한계, 2진 소수점 표현의 한계

program/program_basic 2012. 10. 5. 10:47
반응형

Q. 부동소수점의 표현의 한계에 대해 알아보자.



1. double 형 0.333


double dbl = 0.333;
System.out.println( dbl );



위 소스의 값은 0.333이 나온다. 그러므로 다른 사람들은 이것에 이의를 제기 하지 않았을 것이다.


하지만, 2진 변환 과정에서 위 수치 계산은 무한히 반복된다.

IEEE754 배정도 실수 유효 비트수인 52비트까지를 표현하면 아래와 같다,


0011111111010101010011111101111100111011011001000101101000011101 (2진수)


이 계산은 무한히 반복됨에도 불구하고 double 형이

표현할수 있는 비트 수의 제한이 있으므로 정확한 값의 표현이 불가능하다.

위의 숫자를 소수 60자리로 하여 10진수로 표현하면 아래와 같다.


0.333000000000000018207657603852567262947559356689453125000000 (10진수)


실제로 입력은 0.333이지만

시스템 내부에서 갖고 있는 근사치는 0.3330000000000000182.... 과 같다.


하지만 System.out.println( dbl ); 의 값은 0.333 이 나온다?


그것은 System.out.println( double ); 을 따라가 보면

sun.misc.FloatingDecimal.getChars 이 메소드가 포메팅을 수행하여

보기좋은 숫자 (내부적으로는 0.333의 가장 근사치인) 0.333 이라는 결과를 나타낸다.






2. double형 4.35 * 0.9 = 값은?


윈도우 계산기로 두드려본 결과 3.915 가 나온다.

프로그램도 같을까 ?


double a = 0.9;
double b = 4.35;

System.out.println( a * b );


위의 결과값은 3.9149999999999996 이다.

궁금하면 이클립스 실행 ㄱㄱ


이는 3.915의 가장 가까운 근사치이다.


우리 회사에서 제공하는 Round 함수는 (java JDK 6.x 기반)


Round(수식, 반올림자릿수)


Round(1/3, 3) 의 연산이 0.333 이 나와야 하는 경우가 있다.

하지만 double 형을 채택하고 있는 위 함수는 0.333을 표현할 수 없다.



그래서 !

Round_Fuzz 라는 임의값을 더하여 보정을 하고 있다.

Round_Fuzz 의 임의값을 정해야 하는데,

Round_Fuzz 값이 너무 낮으면, 

   3.9149999999999996

   0.0000000000000001 을 더하게 되면 (Round_Fuzz)

   3.9149999999999997 이 되서 아무런 변화가 없게 되고


Round_Fuzz 값이 너무 높으면, 당연히 오차 범위가 커지게 된다.


그래서 아래와 같은 소스를 돌려본 결과


double n = 10000.285;
Random rand = new Random( System.currentTimeMillis() );

for( int i = 0; i < 1000; i++ )
{
        double op1 = rand.nextDouble() * (double)( i % 10 + 1 );
        double op2 = 1.0 / op1;

        if( i % 2 == 0 )
                n = n * op1 * op2;
        else
                n = Math.pow( Math.pow( n, op1 ), op2 );
        
        System.out.println( new BigDecimal( n ) );
        
        Math.round( n );
}



통계적으로 그나마 0.00000000001 이 적합하다고 계산된다.





3. 결론


컴퓨터라고 해서 초 정밀한 결과를 내주는것은 아니며,

double 형의 제길슨한 2진 표현 방식은 너무도 어렵기 때문에,

한참을 들여다 보지 않는 이상 "나는" 알수가 없었고,


double 은 double 의 곱의 결과가 어쩌면 약간의 오차가 나올수 있다.


컴터는 어렵다 (ㅠ_ㅠ)

반응형

[java] 현재 시스템 시간 가져오기, 오늘 날짜 가져오기

program/java 2012. 10. 5. 10:39
반응형

Q. 오늘 날짜, 시간을 가져온다.




오늘 시간을 가져오기 위해선,


Calendar 클래스를 가져와야 합니다.


전에는 Date 를 사용해서 날짜와 시간을 처리하였으나,


JDK1.1 부터 보다 기능이 향상된 Calendar 가 추가 되었습니다.


Date 는 이전에 사용되어 왔기 때문에, 호환여부를 위해서 아직 남아있는 소스지만,


언젠가는 없어질것으로 공지하고 있습니다.





import java.text.SimpleDateFormat;
import java.util.*;

public class TodayTime
{
	public static void main( String[] args )
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime( new Date( System.currentTimeMillis() ) );
		String date = new SimpleDateFormat( "yyyy-MM-dd hh:mm:ss" ).format( cal.getTime() );

		System.out.println( date );
	}
}


반응형

[java] 오라클 DB 연결 예제

program/java 2012. 10. 5. 10:21
반응형


Q. 자바 프로그램으로 오라클 DB 를 접근해보자.





우선 ojdbc6.jar (2012.10.05 기준 최신버전) 을 다운 받는다.


http://www.oracle.com/technetwork/database/features/jdbc/index-091264.html


또는


파일을 클릭하여 다운 받는다.


ojdbc6.jar



위 사이트를 방문하면 목록에서 가장 최신 버전의 ojdbc6.jar 파일을 받는다.


ojdbc6.jar 클래스를 사용하기 위해선, 사용할 프로젝트의 빌드 패스에 추가하여야 하는데,


프로젝트 우클릭 -> Properties -> Java Build Path -> Libraries -> Add JARs -> 파일 선택을


하면 ojdbc6.jar 파일을 자신의 프로젝트의 빌드 패스에 추가할수 있다.



OracleDBConnect.java

import java.sql.*;

public class OracleDBConnect
{
	public static void main( String[] args ) throws Exception
	{

		Statement stmt = null;
		Connection conn = null;
		String url = "jdbc:oracle:thin:@localhost:1521:ORCL";
		String id = "id";
		String pw = "pw";

		try
		{
			Class.forName( "oracle.jdbc.driver.OracleDriver" );
			conn = DriverManager.getConnection( url, id, pw );

			stmt = conn.createStatement();
			String sql = "SELECT * FROM TEST";

			ResultSet rs = stmt.executeQuery( sql );

			while( rs.next() )
			{
				String name = rs.getString( 1 );
				String value = rs.getString( 2 );
				System.out.println( name + "\t" + value );
			}
			rs.close();

		}
		catch( SQLException e )
		{
			throw new SQLException( e.getMessage(), e.getCause() );
		}
		catch( ClassNotFoundException e )
		{
			throw new ClassNotFoundException( e.getMessage(), e.getCause() );
		}
		finally
		{
			if( stmt != null )
				try
				{
					stmt.close();
					conn.close();
				}
				catch( SQLException e )
				{
				}
		}
	}
}


실행하게 되면 해당 DB에서 값을 가져 올수 있다.

반응형

[java] Switch Case 사용법

program/java 2012. 10. 5. 09:20
반응형

Q. Switch Case 를 사용해 보자.





if 문과 더불어 조건문중에서 가장 많이 쓰는 Switch Case 문 입니다.


사용에 있어 크게 어려움은 없으나,


break 와 default 를 사용하기 때문에 간단하게만 알고 계시면 됩니다.




기본적으로는 아래와 같이 사용하시면 됩니다.



class SwitchCase
{
	public static void main( String[] args )
	{
		int div = 2;
		switch( div )
		{
		case 1:
			System.out.println( "1 입니다." );
			break;
		case 2:
			System.out.println( "2 입니다." );
			break;
		case 3:
			System.out.println( "3 입니다." );
			break;
		default:
			System.out.println( "default 입니다." );
			break;
		}
	}
}


switch 에서 입력된 값에 따라, 


case 구문으로 이동하여 실행하고, break 를 만나게 되면 switch 문을 빠져나오게 됩니다.


만약 div 의 값이 1, 2, 3 이외의 값이 입력된다면,


case 문 어디에도 해당하지 않기 때문에,


default 구문을 실행하고 빠져나오게 됩니다.





그럼 break 문이 없을때는 어떻게 될까요.


간단한 예제를 보여드리겠습니다.



class SwitchCase
{
	public static void main( String[] args )
	{
		int grant = 4;
		switch( grant )
		{
		case 4:
			grantDelete();
		case 3:
			grantCreate();
		case 2:
			grantUpdate();
		case 1:
			grantRead();
			break;
		default:
			System.out.println( "권한 밖입니다." );
		}
	}

	private static void grantRead()
	{
		System.out.println( "읽기 권한이 부여 되었습니다." );
	}

	private static void grantUpdate()
	{
		System.out.println( "수정 권한이 부여 되었습니다." );
	}

	private static void grantCreate()
	{
		System.out.println( "생성 권한이 부여 되었습니다." );
	}

	private static void grantDelete()
	{
		System.out.println( "삭제 권한이 부여 되었습니다." );
	}
}


break 문이 없게되면 해당 구문 실행후 아래 case 문으로 이동하여 실행합니다.


grant 의 값이 4 라면 4, 3, 2, 1 을 순서대로 실행하여 모든 권한을 갖게 됩니다.


반응형

[java] Sun 에서 권고하는 코딩 지침 & 명명 규칙

program/java 2012. 10. 3. 22:01
반응형

1. 패키지명은 모두 소문자로 작성한다.

 - mypackage

 

2. 클래스명은 대문자로 시작한다.
 - MyClass

 

3. 변수의 이름은 소문자로 시작한다.
 - account, eventHandler

 

4. 상수는 모두 대문자로 작성하고 '_' 를 사용하여 단어를 구분한다.
 - MAX_ITERATIONS = 25

 

5. 메소드의 이름은 동사를 사용하며 소문자로 시작한다.
 - getName()
 - setName()

 

6. private 접근 제한자를 갖는 클래스 변수에 '_' 접미사를 사용한다.
 - private int depth_;

 

7. 일반적인 변수의 이름은 타입의 이름과 동일하게 지정한다.
 - void setTopic(Topic topic)

 

8. 모든 이름은 영어로 작성한다.

반응형

[java] 클래스 상속 & 메소드 오버라이딩 예제

program/java 2012. 10. 3. 21:19
반응형

클래스를 응용해서 작성할일이 생기게 됩니다.


그렇다면 기존에 만들어진 클래스를 다시 또 만들어서 수정해야하는데,


이를 좀더 편하게 할수 있는 방법이 있습니다.


그게 바로 상속과 오버라이드 입니다.





상속은 기존의 클래스를 그대로 가져와서 사용하는 것입니다.


그리고 기존의 클래스에서 수정하고 싶은 부분을 고쳐서 사용하는 것이


바로 메소드 오버라이딩 입니다.




간단히 예제를 보시면 됩니다.


Animal.java

class Animal
{
	private String name;
	private int age;

	public void bark()
	{
		System.out.println( "동물소리" );
	}

	public void eat()
	{
		System.out.println( "동물먹기" );
	}

	public String getName()
	{
		return name;
	}

	public void setName( String name )
	{
		this.name = name;
	}

	public int getAge()
	{
		return age;
	}

	public void setAge( int age )
	{
		this.age = age;
	}
}




Dog.java

class Dog extends Animal
{
	// 메소드 오버라이딩
	public void bark()
	{
		System.out.println( "멍멍" );
	}

	public void eat()
	{
		System.out.println( "개사료" );
	}
}




Cat.java

class Cat extends Animal
{
	// 메소드 오버라이딩
	public void bark()
	{
		System.out.println( "야옹" );
	}

	public void eat()
	{
		System.out.println( "우유" );
	}
}




Test.java

class Test
{
	public static void main( String[] args )
	{
		Animal animal = new Animal();
		animal.setName( "동물" );
		animal.setAge( 10 );
		animal.bark();
		animal.eat();

		System.out.println();

		Dog dog = new Dog();
		dog.setName( "멍멍이" );
		dog.setAge( 5 );
		dog.bark();
		dog.eat();

		System.out.println();

		Cat cat = new Cat();
		cat.setName( "고양이" );
		cat.setAge( 6 );
		cat.bark();
		cat.eat();
	}
}


위의 예제를 보게되면,


Dog 와 Cat 모두 Animal 을 상속 받았고,


Animal 안에 있는 짖는 소리(bark)와 먹는 음식(eat) 이 다르기 때문에,


2가지를 오버라이딩 하여 값을 수정하였습니다.



예제를 실행해보면서 확인해보면 쉽습니다.

반응형

[java] 클래스 예제, class 이해를 돕기 위한 예제

program/java 2012. 10. 2. 22:23
반응형

클래스라는 개념을 이해하기 위한 예제 입니다.




흔히 객체지향 언어에서는 객체와 클래스라는 개념을 많이 사용하게 되는데,


그중 클래스에 대해서 간단하게 설명을 해볼까 합니다.




클래스는 쉽게 생각하여 데이터를 담아놓는 형태 또는 틀이라고 생각하면 됩니다.




아래 소스는 Student 소스 입니다.


Student.java

class Student
{
	public static void main( String[] args )
	{
		StudentForm s1 = new StudentForm();
		StudentForm s2 = new StudentForm();
		StudentForm s3 = new StudentForm();

		s1.setName( "철수" );
		s1.setAge( 20 );

		s2.setName( "영희" );
		s2.setAge( 30 );

		s3.setName( "길동" );
		s3.setAge( 40 );

		System.out.println( s1.getName() + " : " + s1.getAge() );
		System.out.println( s2.getName() + " : " + s2.getAge() );
		System.out.println( s3.getName() + " : " + s3.getAge() );
	}
}

Student 라는 클래스 에선 StudentForm 이라는 클래스를 선언하여 사용합니다.


그러면 StudentForm 클래스는 어떻게 생겼는지 살펴보겠습니다.


StudentForm.java

class StudentForm
{
	private String name;
	private int age;

	public String getName()
	{
		return name;
	}

	public int getAge()
	{
		return age;
	}

	public void setName( String name )
	{
		this.name = name;
	}

	public void setAge( int age )
	{
		this.age = age;
	}
}

StudentForm 은 매우 간단하게 생겼습니다.


StudentForm 안에 데이터로는 name, age 두개를 가지게 되며,


StudentForm 클래스로 생성되는 아이들에게는 모두 name 과 age 2개의 변수를 가지게 됩니다.




Student 에서 만들어진


StudentForm 타입의 s1, s2, s3 는 setName, setAge 로 인해서


각각의 다른 값을 가지게 되며,


getName, getAge 를 할때또한 각각의 값을 가져오게 됩니다.


반응형

[java] 빙고 만들기, 빙고판 만들기

program/java 2012. 9. 30. 01:08
반응형

1. 우선 5 x 5 크기의 빙고판에 1부터 25까지 숫자를 순서대로 넣는다.


2. 넣어져 있는 배열의 숫자를 마구 섞는다.





class Bingo
{
	private static int[][] arr = new int[5][5];

	public static void main( String args[] )
	{
		generate();
		swap( 50 );
		print();
	}

	private static void generate()
	{
		int cnt = 1;

		for( int i = 0; i < 5; i++ )
			for( int j = 0; j < 5; j++ )
				arr[i][j] = cnt++;
	}

	private static void swap( int shuffle )
	{
		int[] s = new int[4];
		int temp;

		for( int j = 0; j < shuffle; j++ )
		{
			for( int i = 0; i < 4; i++ )
				s[i] = rand();

			// Swap
			temp = arr[s[0]][s[1]];
			arr[s[0]][s[1]] = arr[s[2]][s[3]];
			arr[s[2]][s[3]] = temp;
		}
	}

	private static void print()
	{
		for( int i = 0; i < 5; i++ )
		{
			for( int j = 0; j < 5; j++ )
				System.out.print( arr[i][j] + "\t" );
			System.out.println();
		}
	}

	private static int rand()
	{
		return (int)( Math.random() * 5 );
	}
}
반응형

[java] 자바 야구게임

program/java 2012. 9. 30. 00:56
반응형

자바로 야구 게임을 만들어 보았다.


발로 짰다..;






import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Baseball
{
	private static int[] arr = new int[3];
	private static int[] answer = new int[3];
	private static int strike = 0;
	private static int ball = 0;
	private static int out = 0;

	public static void main( String args[] )
	{
		start();
	}

	public static void start()
	{
		while( true )
		{
			answer();
			input();
			check();
			print();
		}
	}

	public static void answer()
	{
		boolean flag = true;

		while( flag )
		{
			for( int j = 0; j < 3; j++ )
				for( int k = 0; k < 3; k++ )
					if( j != k && answer[j] == answer[k] )
						for( int i = 0; i < 3; i++ )
							answer[i] = (int)( Math.random() * 9 + 1 );
					else
						flag = false;
		}

		System.out.println( "\n\nAnswer : " + answer[0] + answer[1] + answer[2] + "\n" );
	}

	public static void input()
	{
		String inputStr = "";
		int inputNum = 0;

		BufferedReader in = new BufferedReader( new InputStreamReader( System.in ) );

		System.out.print( "input num : " );

		boolean input = true;
		while( input )
		{
			try
			{
				inputStr = in.readLine();
				inputStr = inputStr.replaceAll( " ", "" );
				inputNum = Integer.parseInt( inputStr );
				input = false;
			}
			catch( Exception e )
			{
				System.out.println( "Only Number.." );
			}
		}

		arr[0] = inputNum / 100;
		inputNum -= arr[0] * 100;
		arr[1] = inputNum / 10;
		inputNum -= arr[1] * 10;
		arr[2] = inputNum;
	}

	public static void check()
	{
		for( int i = 0; i < 3; i++ )
		{
			if( arr[i] == answer[i] )
				strike++;

			for( int k = 0; k < 3; k++ )
				if( i != k && arr[i] == answer[k] )
					ball++;
		}
		if( strike == 0 && ball == 0 )
			out++;
	}

	public static void print()
	{
		System.out.println( "Strike : " + strike );
		System.out.println( "Ball   : " + ball );
		System.out.println( "Out    : " + out );

		if( strike == 3 )
		{
			System.out.println( "\n\n############ Game Success ############" );
			System.exit( 1 );
		}
		else if( out == 10 )
		{
			System.out.println( "\n\n############ Game Failed ############" );
			System.exit( 1 );
		}
		strike = 0;
		ball = 0;
	}
}
반응형

[java] 오라클 연결 예제

program/java 2012. 9. 28. 14:54
반응형

오라클 디비 연결 예제

 

 

 

 

import java.sql.*;
import java.util.Scanner;

class OracleConnectSample
{
	public static void main( String[] args )
	{
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;

		try
		{
			Class.forName( "oracle.jdbc.driver.OracleDriver" );
			conn = DriverManager.getConnection( "jdbc:oracle:thin:@localhost:1521:orcl", "id", "pw" );
			stmt = conn.createStatement();
			rs = stmt.executeQuery( "SELECT * from CUST_PROD" );

			while( rs.next() )
			{
				String custId = rs.getString( "CUST_ID" );
				String prodCd = rs.getString( "PROD_CD" );
				int principal = rs.getInt( "PRINCIPAL" );
				String purchaseDay = rs.getString( "PURCHASE_DAY" );
				int term = rs.getInt( "TERM" );
			}
		}
		catch( SQLException sqle )
		{
			System.out.println( sqle.getMessage() );
		}
		catch( ClassNotFoundException cnfe )
		{
			System.out.println( cnfe.getMessage() );
		}

		finally
		{
			try
			{
				rs.close();
				stmt.close();
				conn.close();
			}
			catch( Exception ignoled )
			{
			}
		}
	}
}
반응형