[C++]부호와 크기, 1의 보수, 2의 보수(+GUI(Qt)활용)

부호-보수1, 2 변환

  • 10진수 -> 부호-보수1, 2 변환하는 알고리즘
  • 출력화면을 통해 알고리즘 이해
  • Qt(GUI)로 구현


부호와 크기, 1의 보수, 2의 보수 변환 예시

“음의 정수” 즉, “보수” 구하는 3가지 방법 (ex:-4)

  1. 양수값을 8비트로 표현 : 00000100
  2. 부호와 크기 방식으로 표현 : 10000100
    • 첫번째 bit는 부호bit 로써 0이면 “양수”, 1이면 “음수”로 표현
  3. 1의 보수 형태 : 11111011
    • 0을 1로, 1을 0으로 변환해서 표현 -> 부호bit 빼고
  4. 2의 보수 형태 : 11111100
    • 1의 보수에 1더해서 표현


출력화면

  • 8bit로 설정후 숫자 입력한 상황 (종료는 q입력시 종료)
# 숫자 입력 : 4 -> 양수는 보수 구하는게 아니니까 그대로 출력나오는 것
부호와 크기 형태 : 00000100
1 보수 형태 : 00000100
2 보수 형태 : 00000100
    
# 숫자 입력 : -4
부호와 크기 형태 : 10000100
1 보수 형태 : 11111011
2 보수 형태 : 11111100


1. main.cpp

#include "QtWidgetsApplication1.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QtWidgetsApplication1 w;
    w.show();
    return a.exec();
}


2. QtWidgetsApplication1.ui

UI화면이 나옴. 여기서 UI 자유롭게 꾸밀 수 있음.


3. QtWidgetsApplication1.h

  • 헤더 파일이다.
#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication1.h"

class QtWidgetsApplication1 : public QMainWindow
{
    Q_OBJECT

public:
    QtWidgetsApplication1(QWidget *parent = Q_NULLPTR);

private:
    Ui::QtWidgetsApplication1Class ui;
public slots:
    void changeButtonClick();
};


4. QtWidgetsApplication1.cpp

  • 여기가 핵심 소스(알고리즘 시작 주석있는 부분을 중점으로 확인)
#pragma warning(disable:4996)
#include <iostream>
#include <string> // string 사용하기위해
#include <algorithm> // reverse 사용하기위해
#include <cstdlib> // abs 사용하기 위해
#include <cmath> // 제곱 사용 위해
#include "QtWidgetsApplication1.h"

using namespace std;

QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
}


void QtWidgetsApplication1::changeButtonClick() {
	QString a = ui.lineEdit->text();
    string input;
    input = a.toStdString(); // 입력숫자 저장
	int whatBit; // 입력비트 저장
	if (ui.radioButton_8bit->isChecked()) {
		whatBit = 8;
	}
	else if(ui.radioButton_16bit->isChecked()) {
		whatBit = 16;
	}
	else if (ui.radioButton_32bit->isChecked()) {
		whatBit = 32;
	}
	else if (ui.radioButton_64bit->isChecked()) {
		whatBit = 64;
	}
	string whatTF; // T/F 확인용
	int input_Number;
	int minNum = pow(2, whatBit - 1);

	if (input.compare("q") == 0) close(); // 종료

	string str = "-" + to_string(minNum); // int형 문자열로 변환
	if (input.compare("-0") == 0 || input.compare(str) == 0) whatTF = "t";
	else whatTF = "f";

	if (whatTF.compare("t") == 0) { // t인 경우
		input_Number = atoi(input.c_str());

		if (input_Number == 0) { // => 수정 불필요
			string a = "1";
			string b = "1";
			// 부호-크기
			for (int i = 1; i < whatBit; i++) {
				a = a + "0";
			}
			QString aa = QString::fromLocal8Bit(a);
			ui.label_result_1->setText(aa);
			// 1의 보수
			for (int i = 1; i < whatBit; i++) {
				b = b + "1";
			}
			QString bb = QString::fromLocal8Bit(b);
			ui.label_result_2->setText(bb);
			// 2의 보수
			ui.label_result_3->setText("-"); 
		}
		else if (input_Number == -minNum) { // => 수정 불필요
			string c = "1";
			for (int i = 1; i < whatBit; i++) {
				c = c + "0";
			}
			QString cc = QString::fromLocal8Bit(c);
			ui.label_result_3->setText(cc);
			ui.label_result_2->setText("-");
			ui.label_result_1->setText("-");
		}
		else {
			QString dd = QString::fromLocal8Bit("알맞은 숫자를 입력하지 않았습니다.");
			ui.label_result_1->setText(dd); // 예외처리
			ui.label_result_2->setText("");
			ui.label_result_3->setText("");
			return;
		}
	}
	else { // f인 경우(즉, -0과 더 작은숫자는 신경 안써도 됨)
		input_Number = atoi(input.c_str());
		if (input_Number <= (minNum - 1) && input_Number >= -(minNum - 1)) {
			// 알고리즘 시작
			// 10진수를 2진수로 변환하려면 10진수를 2로 나누어 몫 과 나머지를 구한 후 나머지는 출력할 배열에 저장하고
			// 몫은 또 2로나누어 나머지를 구하여 출력할 배열에 저장하는 과정을 몫이 0이 될때까지 무한반복 후 몫이 0이되었을경우 저장한 출력배열을 거꾸로 출력시키면 됩니다.
			int* arrSign = new int[whatBit]; // 동적배열 할당(bit마다 다르기때문)
			int* arrOne = new int[whatBit];
			int* arrTwo = new int[whatBit];

			for (int i = 0; i < whatBit; i++) {
				arrSign[i] = 0; // 0으로 초기화
				arrOne[i] = 0;
				arrTwo[i] = 0;
			}
			if (input_Number < 0) { // 음수의 경우 해줘야할 부분(-0신경안쓰는거 까먹지 말기)
				arrSign[whatBit - 1] = 1; // 마지막 1로 초기화
				arrOne[whatBit - 1] = 1;
				input_Number = abs(input_Number); // 양수로 변환하기
			}
			int quotient = input_Number; // 초기화(몫)
			int remainder = input_Number; // 초기화(나머지)
			int arrIndex = 0; // arr배열의 index
			// 양수의 경우
			while (quotient != 0) {
				remainder = quotient % 2;
				quotient = quotient / 2;
				arrSign[arrIndex] = remainder;
				arrOne[arrIndex] = remainder;
				arrIndex++;
			}
			// arr배열 reverse해주기.
			reverse(arrSign, arrSign + whatBit);
			reverse(arrOne, arrOne + whatBit);
			// 부호-크기
			string a;
			for (int i = 0; i < whatBit; i++) {
				a += to_string(arrSign[i]);
			}
			QString aa = QString::fromLocal8Bit(a);
			ui.label_result_1->setText(aa);
			// 1의 보수
			string b;
			for (int i = 0; i < whatBit; i++) {
				if (arrOne[0] == 1) { // 음수의 경우 출력 부분
					if (i == 0) {
						b += to_string(arrOne[i]);
						arrTwo[i] = arrOne[i];
						continue;
					}
					if (arrOne[i] == 0) arrOne[i] = 1;
					else arrOne[i] = 0;
					b += to_string(arrOne[i]);
					arrTwo[i] = arrOne[i];
				}
				else { // 양수의 경우 출력 부분
					b += to_string(arrOne[i]);
					arrTwo[i] = arrOne[i];
				}
			}
			QString bb = QString::fromLocal8Bit(b);
			ui.label_result_2->setText(bb);
			// 2의 보수
			string c;
			if (arrTwo[0] == 1) { // 음수의 경우 출력 부분
				arrTwo[whatBit - 1] += 1; // 배열 끝 인덱스에 +1
				if (arrTwo[whatBit - 1] == 2) { // 올림수 있음.
					arrTwo[whatBit - 1] = 0; // 그자리는 0이 된다.
					for (int i = 1; i < whatBit; i++) {
						arrTwo[whatBit - 1 - i] += 1;
						if (arrTwo[whatBit - 1 - i] == 2) {
							arrTwo[whatBit - 1 - i] = 0;
							continue;
						}
						else { // 올림수 없음.
							break; // for문 탈출
						}
					}
				}
				else { // 올림수 없음.
					// pass
				}
				for (int i = 0; i < whatBit; i++) {
					c += to_string(arrTwo[i]);
				}
			}
			else { // 양수의 경우 출력 부분
				for (int i = 0; i < whatBit; i++) {
					c += to_string(arrTwo[i]);
				}
			}
			QString cc = QString::fromLocal8Bit(c);
			ui.label_result_3->setText(cc);
			delete[] arrSign;
			delete[] arrOne;
			delete[] arrTwo;
		}
		else {
			QString dd = QString::fromLocal8Bit("범위내에 숫자를 입력하지 않았습니다.");
			ui.label_result_1->setText(dd); // 예외처리
			ui.label_result_2->setText("");
			ui.label_result_3->setText("");
			return;
		}
	}		
}

댓글남기기