출처 : 종만북 5.4 다른 기술들 - 순환 소수 찾기

코드설명

순환소수를 찾습니다.

HashMap을 활용하여 소수점에서부터의 숫자, 피연산자인 숫자가 다시 한번 보인다면 해당 숫자는 순환소수입니다.

이에 맞추어서 무한소수 이전부분과 무한소수 이후부분을 나누어서 String을 재조립한뒤 출력하면, 순환소수를 찾을 수 있습니다. 

 

당연히 같은 수로 같은 숫자를 나누면, 무한하게 같은 형태의 나머지가 지속될 것임을 알 수 있습니다. 이러한 부분이 비둘기 집의 원리가 적용되었습니다.

 

순환소수를 구현하며 아래의 hashmap에 왜 a%b 가 아닌 a를 넣는지 궁금합니다.

이유는, 맨 처음에 밖에서 a = (a%b)*10 으로 들어오고, while문의 마무리도 a = a%b * 10; 으로 마무리되기에 hashmap에도 처음 들어온 a = (a%b)*10 형태로 삽입하여주어야 합니다.

좀 헷갈릴 수 있지만, 생각해보면 알 수 있습니다.

hashmap.put(a, sb.length());

 

 

입력 예시 1

3 8

결과 예시 1

0.375

 

입력 예시 2

4712 400

결과 예시 2

11.78

 

입력 예시 3

1 11

결과 예시 3

0.(09)

입력 예시 4

22 7

출력 예시 4

3.(142857)

코드

순환소수를 고려한 코드입니다.

package Main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.StringTokenizer;
 
public class Main {
	public static int C, N, M;
	public static int answer = Integer.MAX_VALUE;
	
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		printDecimal(N, M); // N/M을 실수 연산을 쓰지 않고 이 분수를 소수 형태로 출력하라.
	}
	
	public  static void printDecimal(int a, int b) {
        StringBuilder result = new StringBuilder();
        HashMap<Integer, Integer> remainderMap = new HashMap<>();
        
        int integerPart = a / b;
        result.append(integerPart);
        
        a = (a % b) * 10;
        if (a > 0) {
            result.append(".");
        }
        
        while (a > 0) {
            // 나머지가 이미 등장한 적이 있는지 확인
            if (remainderMap.containsKey(a)) {
                int start = remainderMap.get(a);
                String nonRepeatingPart = result.substring(0, start);
                String repeatingPart = result.substring(start);
                result = new StringBuilder(nonRepeatingPart + "(" + repeatingPart + ")");
                break;
            }
            remainderMap.put(a, result.length());
            result.append(a/b);
            a = (a % b) * 10;
        }
        
        System.out.println(result.toString());
    }
}

 

순환소수를 고려하지 못한 코드입니다. 1/11 일경우 0.0909090909 ... 가 무한합니다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
	public static int C, N, M;
	public static int answer = Integer.MAX_VALUE;
	
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		printDecimal(N, M); // N/M을 실수 연산을 쓰지 않고 이 분수를 소수 형태로 출력하라.
	}
	
	public static void printDecimal(int a, int b) {
		int iter = 0;
//		while(a % b != 0) { // 이렇게 처리할경우 while문이 끝나고 한번 더 따로처리해야하여 비효율적입니다.
		while(a > 0) {
			if(iter++ == 1) System.out.print(".");
			System.out.print(a / b);
			a = (a % b) * 10;
		}
		
	}
}

 

순환소수 고려하지 않은 코드 2.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main {
	public static int C, N, M;
	public static int answer = Integer.MAX_VALUE;
	
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		printDecimal(N, M); // N/M을 실수 연산을 쓰지 않고 이 분수를 소수 형태로 출력하라.
	}
	
	
	// 1 11
	public static void printDecimal(int a, int b) {
		StringBuilder sb = new StringBuilder();
		int integerPart = a / b;
		sb.append(integerPart);
		a = (a % b) * 10;
		if( a > 0) { //아직 나머지가 존재한다면, 소수점이 존재한다는 의미입니다.
			sb.append(".");
		}
		
		while(a > 0) {
			sb.append(a/b);
			a = (a%b) * 10;
		}
		System.out.println(sb);
	}
}

+ Recent posts