본문 바로가기
카테고리 없음

진수 변환 정리 & 진수 변환 트릭 프로그램

by SuldenLion 2023. 3. 30.
반응형

며칠전 연구실 동생 아누삭이 진수 변환하는 법을 물어봐서 알려준 기억이 있는데, 이를 좀 구체적으로 정리해보고 예전에 만든 진수 변환 트릭 프로그램도 소개해보도록 하겠다.

 

우리가 사용하는 수의 체계인 10진법(Decimal)은 컴퓨터 내에서 2진법(Binary), 8진법(Octal), 16진법(Hexadecimal) 등으로 사용된다.

 

우선, 위와 같은 진법들의 사용 이유에 대해 간단히 알아보자면, 컴퓨터는 1과 0의 두 가지 상태밖에 표현하지 못한다. 하지만 이런 단순한 연산 구조를 가지고 필요한 모든 정보를 함축하고 모든 연산을 해낼 수 있다. 10진수의 모든 수를 2진수로 표현할 수 있으며 이것은 전기 신호가 켜지고 꺼지는 두 가지 조합을 통해서 우리가 사용하는 모든 수를 표현할 수 있는 것이다.

 

즉, 2진수로 10진수, 8진수, 16진수 모두를 표현할 수 있다.

 

8진수, 16진수는 2진수의 가독성 향상을 위한 방식이며 특정한 경우에 쓰인다.

- 8진수를 사용하는 대표적인 예는 리눅스나 FTP 등에서 파일이나 폴더에 관한 권한을 표현하기 위해 많이 쓰인다.

- 16진수는 통신 쪽과 같이 대용량의 데이터가 사용될때, 2진수로 표현하기에는 너무 길어지는 데이터를 짧게 표현하기 위해 사용한다.

 

 

이제부터 어떤 특정 진수의 숫자가 주어지고 그 숫자를 또 다른 진수로 표현하려면 어떻게 해야 되는지 알아보겠다.

 

십진수의 숫자 '10'이 주어지고 이를 각각의 진법으로 바꿔보겠다.

먼저 2진수이다.

2진수는 곧 각 자리가 2^0, 2^1, 2^2 ... 으로 표현되는데, '10'에 해당하는 숫자를 2^n의 조합(2^3+2^1)으로 표현해내면 된다.

 

+ Java에서 간단하게 진수변환을 테스트 해보고자 한다면

위의 코드를 돌려보면 된다. toString과 parseInt 각각의 두번째 parameter에 2/8/16을 명시함으로써 해당 진수들로의 변환을 확인해 볼 수 있다.

 

 

다음은 십진수 '10'을 8진수로 변환해 보겠다.

8진수는 2^2와 2^1, 2^0으로 표현해야 하는 수이다. 

십진수에서 8진수를 표현하기 위해서는 2진수를 거쳐간 후, 그것을 세 덩어리씩 나누어서 표현하면 된다.

'10'의 8진수 표현은 12가 될 것이며, 코드로는

이렇게 될 것이다.

 

 

다음은 16진수이다.

10진법은 '0~9' 10개의 숫자, 8진법은 '0~7' 8개의 숫자이듯이 16진법은 '0~9' 10개의 숫자와 'A~F'까지 6개의 기호를 사용해 총 16개로 수를 나타내는 방법이다.

16진수도 마찬가지로 2진수를 거쳐서 4등분하여 알아내면 된다.

16진수는 '10'이 아닌 다른 수로 해보겠다.

10진수 숫자 '47'을 16진수로 바꿔보자.

어떤 진수로 변환하든(16진수를 8진수로 표현하든, 8진수를 10진수로 표현하든..) 2진수를 거쳐가며 각 진수의 표현 범위만큼 나누어 계산하면 어렵지 않다.

 

 

진수 변환에 대한 정리는 이쯤 마무리하고 다음은 내가 만든 프로그램 「Sulden number magic」을 소개하겠다.

 

예전에 개발자 상식이라는 책을 읽다가 재밌는 부분을 발견했다.

바로 2진수의 특성을 통해 숫자 맞추기라는 트릭을 할 수 있다는 것이었다.

 

<1번 카드>에 들어있는 모든 수는 2진법으로 표현했을 때, 첫째 자리가 1인 수들이다.

<2번 카드>는 두번째 자리가 1인 수들의 모음, <3번 카드>는 세번째 자리가 1...

즉, <n번 카드>는 이진수의 n번째 자리가 1이라는것을 보장한다.

 

위의 트릭을 GUI 윈도우 프로그램으로 만들어보았다.

 

간단하게 만들어 보는 중인 프로그램에 얹어놨는데, 미완성이라 디자인은 살짝 허접하다.

 

끝에 있는 Number Magic을 누르면 MessageBox가 하나 나오고 간단한 안내를 해준다.

 

OK를 누르면 새로 창이 하나 뜨게 되고, 카드를 6개 배치해 주었다.

 

각 카드의 위쪽에 버튼을 둬서 카드를 선택할 수 있게 해주고 선택된 카드는 아래 textField에 표시된다.

 

 

1번, 3번, 5번, 6번의 카드를 선택해보고 어떤 값이 나오는지 확인해보자.

 

 

1, 3, 5, 6번의 카드를 선택한 결과로 53의 숫자가 나왔다.

 

트릭의 규칙대로면 110101이 이진수일 것이고, 이것은 십진수로 53이 된다.

 

 

대충 구현한 프로그램 파일을 공유하며 마무리하겠다.

import java.awt.*;
import java.awt.event.*;
import java.util.*;

import javax.swing.*;

class MagicPanel extends JPanel {
	FunctionPanel functionPanel;
	MagicPanel(FunctionPanel functionPanel) {
		this.functionPanel = functionPanel;
		
		JOptionPane.showMessageDialog(null, "1~64 중 하나의 숫자를 고른 후 그 숫자가 포함된 카드를 선택하시오");
				
		setLayout(new GridLayout(2,3));
		
		JPanel card1Panel = new JPanel();
		card1Panel.setLayout(new BorderLayout());
		card1Panel.setBorder(BorderFactory.createLineBorder(Color.black));
		JButton card1 = new JButton("1번 card");
		card1.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent e) {
				functionPanel.addField("1");
			}
		});
		JTextArea card1Field = new JTextArea("1 3 5 7 9 11\n13 15 17 19 21 23\n25 27 29 31 33 35\n37 39 41 43 45 47\n49 51 53 55 57 59");
		card1Field.setFont(new Font("Consolas", Font.BOLD, 16));
		card1Field.setEditable(false);
		card1Panel.add(card1, "North");
		card1Panel.add(card1Field, "Center");
		
		JPanel card2Panel = new JPanel();
		card2Panel.setLayout(new BorderLayout());
		card2Panel.setBorder(BorderFactory.createLineBorder(Color.black));
		JButton card2 = new JButton("2번 card");
		card2.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent e) {
				functionPanel.addField("2");
			}
		});
		JTextArea card2Field = new JTextArea("2 3 6 7 10 11\n14 15 18 19 22 23\n26 27 30 31 34 35\n38 39 42 43 46 47\n50 51 54 55 58 59");
		card2Field.setFont(new Font("Consolas", Font.BOLD, 16));
		card2Field.setEditable(false);
		card2Panel.add(card2, "North");
		card2Panel.add(card2Field, "Center");
		
		JPanel card3Panel = new JPanel();
		card3Panel.setLayout(new BorderLayout());
		card3Panel.setBorder(BorderFactory.createLineBorder(Color.black));
		JButton card3 = new JButton("3번 card");
		card3.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent e) {
				functionPanel.addField("3");
			}
		});
		JTextArea card3Field = new JTextArea("4 5 6 7 12 13\n14 15 20 21 22 23\n28 29 30 31 36 37\n38 39 44 45 46 47\n52 53 54 55 60");
		card3Field.setFont(new Font("Consolas", Font.BOLD, 16));
		card3Field.setEditable(false);
		card3Panel.add(card3, "North");
		card3Panel.add(card3Field, "Center");
		
		JPanel card4Panel = new JPanel();
		card4Panel.setLayout(new BorderLayout());
		card4Panel.setBorder(BorderFactory.createLineBorder(Color.black));
		JButton card4 = new JButton("4번 card");
		card4.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent e) {
				functionPanel.addField("4");
			}
		});
		JTextArea card4Field = new JTextArea("8 9 10 11 12 13\n14 15 24 25 26 27\n28 29 30 31 40 41\n42 43 44 45 46 47\n56 57 58 59 60");
		card4Field.setFont(new Font("Consolas", Font.BOLD, 16));
		card4Field.setEditable(false);
		card4Panel.add(card4, "North");
		card4Panel.add(card4Field, "Center");
		
		JPanel card5Panel = new JPanel();
		card5Panel.setLayout(new BorderLayout());
		card5Panel.setBorder(BorderFactory.createLineBorder(Color.black));
		JButton card5 = new JButton("5번 card");
		card5.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent e) {
				functionPanel.addField("5");
			}
		});
		JTextArea card5Field = new JTextArea("16 17 18 19 20 21\n22 23 24 25 26 27\n28 29 30 31 48 49\n50 51 52 53 54 55\n56 57 58 59 60");
		card5Field.setFont(new Font("Consolas", Font.BOLD, 16));
		card5Field.setEditable(false);
		card5Panel.add(card5, "North");
		card5Panel.add(card5Field, "Center");
		
		JPanel card6Panel = new JPanel();
		card6Panel.setLayout(new BorderLayout());
		card6Panel.setBorder(BorderFactory.createLineBorder(Color.black));
		JButton card6 = new JButton("6번 card");
		card6.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent e) {
				functionPanel.addField("6");
			}
		});
		JTextArea card6Field = new JTextArea("32 33 34 35 36 37\n38 39 40 41 42 43\n44 45 46 47 48 49\n50 51 52 53 54 55\n56 57 58 59 60");
		card6Field.setFont(new Font("Consolas", Font.BOLD, 16));
		card6Field.setEditable(false);
		card6Panel.add(card6, "North");
		card6Panel.add(card6Field, "Center");
		
		add(card1Panel);
		add(card2Panel);
		add(card3Panel);
		add(card4Panel);
		add(card5Panel);
		add(card6Panel);
	}
	
}

class FunctionPanel extends JPanel {
	JTextField numField;
	String fieldText;
	JButton okBtn;
	FunctionPanel() {
		numField = new JTextField();
		numField.setPreferredSize(new Dimension(150,30));
		numField.setEditable(false);
		okBtn = new JButton("OK");
		okBtn.addActionListener((e) -> {
			StringTokenizer st = new StringTokenizer(fieldText);
			boolean[] arr = new boolean[6];
			while (st.hasMoreTokens()) {
				int n = Integer.parseInt(st.nextToken());
				arr[n-1] = true;
			}
			int ans = 0;
			for (int i = 0; i < 6; i++) {
				if (arr[i]) {
					switch (i) {
						case 0: {
							ans += 1;
							break;
						}
						case 1: {
							ans += 2;
							break;
						}
						case 2: {
							ans += 4;
							break;
						}
						case 3: {
							ans += 8;
							break;
						}
						case 4: {
							ans += 16;
							break;
						}
						case 5: {
							ans += 32;
							break;
						}
					}
				}
			}
			JOptionPane.showMessageDialog(null, "당신이 고른 숫자는 " + ans + "로군요!");
			numField.setText("");
			fieldText = "";
		});
		add(numField);
		add(okBtn);
	}
	
	void addField(String num) {
		if (fieldText == null) fieldText = num;
		else fieldText += " " + num;
		numField.setText(fieldText);
	}
}

public class Select_NumMagic extends CursorSet {
	ImageIcon frameIcon;
	MagicPanel magicPanel;
	FunctionPanel functionPanel;
	Select_NumMagic() {
		frameIcon = new ImageIcon(MainFrame.class.getResource("img/SulIcon.png"));
		setDefaultCloseOperation(HIDE_ON_CLOSE);
		setSize(650,650);
		setLocationRelativeTo(null);
		setLayout(new BorderLayout());
		setResizable(false);
		setIconImage(frameIcon.getImage());
		setTitle("Sulden number magic");
		
		functionPanel = new FunctionPanel();
		magicPanel = new MagicPanel(functionPanel);
		getContentPane().add(magicPanel, "Center");
		getContentPane().add(functionPanel, "South");
	}	
}
반응형

댓글