[C++]부호와 크기, 1의 보수, 2의 보수(+GUI(Qt)활용)
부호-보수1, 2 변환
- 10진수 -> 부호-보수1, 2 변환하는 알고리즘
- 출력화면을 통해 알고리즘 이해
- Qt(GUI)로 구현
부호와 크기, 1의 보수, 2의 보수 변환 예시
“음의 정수” 즉, “보수” 구하는 3가지 방법 (ex:-4)
- 양수값을 8비트로 표현 : 00000100
- 부호와 크기 방식으로 표현 : 10000100
- 첫번째 bit는 부호bit 로써 0이면 “양수”, 1이면 “음수”로 표현
- 1의 보수 형태 : 11111011
- 0을 1로, 1을 0으로 변환해서 표현 -> 부호bit 빼고
- 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;
}
}
}
댓글남기기