2021.11.26

14919번 연구소

image

위 그림처럼… 맞왜틀(맞았는데 왜 틀림?)을 반복하며 계속 제출을 했지만, 결론적으로 double 형으로 계산시에 0.00000….001 인가 아주 작은 오차가 발생한다는 말을 듣고 String으로 바꾸어서 맞추게 되었다.



[ 풀이 ]

import java.util.*;
import java.io.*;

public class Main {

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int M = Integer.parseInt(br.readLine());
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		ArrayList<String> arr = new ArrayList<String>();
		while(st.hasMoreElements()) {
			arr.add(st.nextToken());
		}
		
		String[] num = new String[arr.size()];
		
		for(int i=0; i<arr.size(); i++) {
			num[i]="";
			boolean isnext = false;
			String nn = arr.get(i);
			for(int j=0; j<nn.length(); j++) {
				if(isnext) {
					num[i] += nn.charAt(j);
				}
				if(nn.charAt(j)=='.') {
					isnext = true;
				}
			}
			while(num[i].length()<6) {
				num[i] += '0';
				if(num[i].length()==6) {break;}
			}
			//System.out.println(num[i]);
		}
		int[] N = new int[arr.size()];
		int[] result = new int[M];
		int MM = 1000000;
		for(int i=0; i<arr.size(); i++) {
			N[i] = Integer.parseInt(num[i]);
			N[i] *= M;
			result[(int)Math.ceil(N[i]/MM)]++;
		}
		
		for(int j=0; j<M; j++) {
			System.out.print(result[j]+" ");
		}

	}

}

문제의 범위가 소수점 6자리까지 이기 때문에 처음부터 1,000,000을 곱해서 자연수로 계산하도록 하였다.

그렇게 num 이라는 배열로 만들고, 만약 0.1과 같이 소수점 6자리가 아닌 경우 0을 추가로 붙여서 자릿수를 맞추었다.


그리고 해당 수에 M(나누는 변수)을 곱한다. M개 마다 어느 구간에 속하는지 구하는 것인데, 원래는 N/M을 해서 해당 값이 어디에 위치하는지 나눈 몫으로 구분하지만….

아까 말한듯 아주 미세한 오차 때문에…

M을 곱함으로 자연수로 바꾸었다. 그리고 해당 값을 1,000,000으로 나눈 몫이 구간을 말하게 된다.


“나누면… 오차가 생긴다고 하셨잖아요…? 왜 1,000,000으로 나누죠?”

이걸 어떻게 설명하면 좋을까를 생각해봤는데,… 오차가 생기는 이유에서 설명하면 좋을 것 같다.

기존 M은 (1 ≤ M ≤ 1,000) 이기 때문에 M에 따라서 무한소수일 가능성이 있다는 것이다.

즉, double에서 생기는 나눗셈 연산시 작은 오차는 가끔 결과를 바꾸는 유의점이 있지만, M이 1,000,000 처럼 무한소수일 가능성이 없다면 오차역시 일어나지 않는다.

“무한소수가 아니면… 오차는 없는 건가?!”

꼭 그런건 아니고…. 하드웨어적으로 무한소수처럼 많은 비트를 요구하는 경우 이런 오차가 생깁니다!

소수점 많은 경우 한정된 비트로 이를 다 표현하지 못해서 오차가 생기는 것이죠! 따라서 0.001 이나 0.5 등 소수점이 적은 경우는 안심하고 사용해도 됩니다.



Tags:

Categories:

Updated:

Leave a comment