[Python]부스 알고리즘_Booth(+GUI)
Booth알고리즘
개념 설명 생략
- 주관적인 생각으로 만들었기 때문에 예외가 많을 수 있다
- 의미 : 부호가 있는 이진수의 곱셈을 수행할 수 있도록 해주는 알고리즘
- 참고 : 입력은 2진수로 받으며, 음수는 2의 보수로 입력
- GUI로 만듬(tkiinter 라이브러리 활용) -> import 생략하겠음
2진수 <-> 10진수 변환 작업이 핵심인 알고리즘이다.
- 곱셈을 10진수로 변환해서 연산 해버리게 만들었기 때문! (1, 2번 확인)
00, 01, 10, 11 에 따른 다른 연산방법이 핵심인 알고리즘이다.
- 3번에 계산부분 확인
1. 2진수 -> 10진수
- 입력받은 2진수를 변수n이라 가정한다면
- 첫째로, 양수인지 음수인지 구분(n의 최상위Bit 활용) => 양수라면 바로 두번째 단계로 넘어가기
- 음수라면?? 최상위Bit는 버리고, 2의보수를 원래형태로 바꾸는 작업이 필요!!(for문 확인)
- 마지막엔 2의보수를 바꿨기 때문에 +1을 꼭 해주고, 음수로 바꾸기위해 -까지 필요
- 두번째로, 변수n을 int형으로 변환해서 num변수에 담아줌(나머지, 나눗셈 구하기 위해)
- 마지막으로, 아래 코드의 while문을 이용시 변환끝.(while문이 여기서의 핵심 알고리즘)
- 첫째로, 양수인지 음수인지 구분(n의 최상위Bit 활용) => 양수라면 바로 두번째 단계로 넘어가기
# 2진수 -> 10진수 (최상위비트 부호)
def convertDecimal(n): # n은 2진수(string)
convertN,rem,i,num = 0,0,0,0
if n[0] == "0": # 양수
num = int(n)
while (num != 0):
rem = int(num % 10)
num = int(num / 10)
convertN = int(convertN + rem * pow(2,i))
i+= 1
else: # 음수
tempStr = n[1:]
str_1 = ""
for j in range(len(tempStr)): # 2의보수를 원래형태로 바꾸는 작업
if tempStr[j] == "0":
str_1 += "1"
else:
str_1 += "0"
num =int(str_1)
while (num != 0): # 101은 rem:1 num:10 num:1 num:0 ... 이런식의 흐름
rem = int(num % 10)
num = int(num / 10)
convertN = convertN + int(rem * pow(2,i))
i+=1
convertN += 1 # 2의보수에서 원래형태로 바꾸기 위해 +1까지 꼭 해주기.
convertN = -convertN # 양수로 구했기 때문에 마지막 음수로 바꾸는 작업까지.
return convertN
2. 10진수 -> 2진수
- 인수로 받은 n은 10진수, whatBit는 몇 비트인지 의미하며, 음수는 2의 보수로 나타낼 것이다.
- 10진수를 2진수로 바꾸는데 bit를 2배로 만들 필요 없다면 while문에 whatBit*2가 아니라 whatBit로.
- 음수라면?? 양수로 바꿔서 똑같이 while문을 이용한다.
- 2의보수로 나타내야 하기 때문에 1의보수로 먼저 바꾼후, 2의보수로 바꿔준다.
- 10진수를 2진수로 바꾸는데 bit를 2배로 만들 필요 없다면 while문에 whatBit*2가 아니라 whatBit로.
# 10진수 -> 2진수 (최상위비트 부호) (음수는 2의보수로 나타내야함.)
def convertBinary(n, whatBit): # n은 10진수, whatBit는 몇비트로 바꿔야 하는지
if(n >= 0): # 양수
quo = n
rem = n
str_1 = ""
while(quo != 0):
rem = int(quo % 2)
quo = int(quo / 2)
str_1 = str(rem) + str_1 # str_1앞에 rem이 붙어야함.
while(len(str_1) != whatBit*2): # bit를 2배로 만들어서 연산할 것이다.
str_1 = "0" + str_1 # 맨앞에 0을 추가.
return str_1
else: # 음수(2의 보수로)
nM = -n # 양수로 전환
quo = nM
rem = nM
str_1 = ""
while(quo!=0):
rem = int(quo % 2)
quo = int(quo / 2)
str_1 = str(rem) + str_1
while(len(str_1)!=whatBit*2):
str_1="0" + str_1
tempStr = str_1
str_1 = ""
for i in range(len(tempStr)): # 1의보수 변환
if(tempStr[i] == "0"): str_1 += "1"
else: str_1 += "0"
arrtwo = []
for i in range(len(str_1)):
arrtwo.append(int(str_1[i]))
# 2의보수 변환
arrtwo[len(arrtwo)-1] += 1
if(arrtwo[len(arrtwo)-1] == 2): # 올림수 있을시
arrtwo[len(arrtwo)-1] = 0 # 그자리는 0
for i in range(1, len(arrtwo)):
arrtwo[len(arrtwo)-1-i] += 1
if(arrtwo[len(arrtwo)-1-i] == 2):
arrtwo[len(arrtwo)-1-i] = 0
continue
else:
break
else: # 올림수 없음
pass
strLeng = len(str_1)
str_1 = ""
for i in range(strLeng):
str_1 += str(arrtwo[i])
return str_1
3. 종료, 시작 버튼
- 계산하는 부분이 중요. 나머지는 중요X
- 승수Bit에 0하나를 더 붙혀서 00, 01, 10, 11 인지 확인하며 각각 다르게 연산하는게 큰 특징이다.
def btnExit():
root.destroy()
def btnStart():
# 먼저, 초기화 시작
inputMultiplicand = entry_Multiplicand.get() # 피승수 가져옴
inputMultiplier = entry_Multiplier.get() # 승수 가져옴
entry_Multiplicand.delete(0, END)
entry_Multiplier.delete(0, END) # 지워줘야 다시 적기 편해서 지움.
txtResult.delete("1.0", END)
whatBit = bit_var.get() # int형임. whatBit
initNum = "0" # 초기화
calTotalNum = "" # 부분합
printLine = "------" # 프린트 선
printAcc = "" # 프린트 부호 공백
printBin = " " # 프린트 공백
initPrintBin = " "
initPrintAcc = ""
lastPrintBin = " "
for i in range(whatBit*2-1):
initNum = initNum + "0"
printLine = printLine + "-"
lastPrintBin = lastPrintBin + " "
for i in range(4): # 4칸정도 띄어서 표시하자.
printAcc = printAcc + " "
printBin = printBin + " "
initPrintBin = initPrintBin + " "
initPrintAcc = initPrintAcc + " "
for i in range(whatBit):
initPrintBin = initPrintBin + " "
initPrintAcc = initPrintAcc + " "
totalNum = 0
multiplicand = convertDecimal(inputMultiplicand)
multiplier = convertDecimal(inputMultiplier)
# 초기 출력 시작
initPrint = ""
initPrint += initPrintBin + inputMultiplicand+ printBin + " "+ f"{multiplicand}" + '\n'
initPrint += "x" + initPrintAcc + inputMultiplier + "0" + printBin + f"{multiplier}" + '\n'
initPrint += printLine + '\n' + printBin + initNum + '\n'
inputMultiplier = inputMultiplier + "0" # 승수엔 0 하나 추가해야함.
calTotalNum = initNum
# 초기 출력 끝
# 계산시작
multiplierIndex = len(inputMultiplier)-1 # 마지막 index
initIndex = multiplierIndex
while(multiplierIndex != 0):
calData = inputMultiplier[multiplierIndex-1:multiplierIndex-1+2] # 끝자리 2개 자른 문자열
if(calData == "00"): # 피승수를 왼쪽 Shift
multiplicand = multiplicand << 1
inputMultiplicand = convertBinary(multiplicand, whatBit)
# 0 더하기 출력, 부분합 출력
initPrint += "+" + printAcc + initNum + '\n' + printLine + '\n' + printBin+calTotalNum + '\n'
elif(calData == "01"): # 피승수를 누적 부분곱에 더한 후 피승수를 왼쪽 Shift
totalNum = convertDecimal(calTotalNum)
totalNum = totalNum + multiplicand
calTotalNum = convertBinary(totalNum, whatBit)
if(initIndex == multiplierIndex): initPrint += "+" + printAcc+printBin+inputMultiplicand + '\n' # 피승수 더하기 출력
else: initPrint += "+" +printAcc + inputMultiplicand + '\n' # 피승수 더하기 출력
# 부분합 출력
initPrint += printLine + '\n' + printBin+calTotalNum + '\n'
multiplicand = multiplicand << 1
inputMultiplicand = convertBinary(multiplicand, whatBit)
elif(calData == "10"): # 피승수를 누적 부분곱에 뺀 후 피승수를 왼쪽 Shift
totalNum = convertDecimal(calTotalNum)
totalNum = totalNum - multiplicand
calTotalNum = convertBinary(totalNum, whatBit) # 문제 발견
if(initIndex == multiplierIndex): initPrint += "-" + printAcc+printBin+inputMultiplicand +'\n' # 피승수 더하기 출력
else: initPrint += "-" +printAcc + inputMultiplicand +'\n' # 피승수 더하기 출력
# 부분합 출력
initPrint += printLine + '\n' + printBin+calTotalNum + '\n'
multiplicand = multiplicand << 1
inputMultiplicand = convertBinary(multiplicand, whatBit)
elif(calData == "11"): # 피승수를 왼쪽 Shift
multiplicand = multiplicand << 1
inputMultiplicand = convertBinary(multiplicand, whatBit)
# 0 더하기 출력, # 부분합 출력
initPrint += "+" + printAcc + initNum + '\n' + printLine + '\n' + printBin+calTotalNum + '\n'
multiplierIndex -= 1
initPrint += lastPrintBin+ f"{totalNum}" + '\n'
# 결과 표시해주는 곳.
txtResult.insert(END,initPrint)
4. GUI
# GUI 설정
root = Tk()
root.title("BoothAlg")
root.geometry("1450x500")
label0 = Label(root, text="입력은 2진수로 입력하세요.(음수는 2의보수로 입력)")
label0.grid(row=0, column=4, padx=3, pady=5)
label1 = Label(root, text="피승수 : ")
label1.grid(row=0, column=0)
entry_Multiplicand = Entry(root, width=30)
entry_Multiplicand.grid(row=0, column=1)
label2 = Label(root, text="승수 : ")
label2.grid(row=1, column=0)
entry_Multiplier = Entry(root, width=30)
entry_Multiplier.grid(row=1, column=1)
# 16bit를 기본값으로 radioButton 설정
label3 = Label(root, text="Bit를 선택하세요")
label3.grid(row=0, column=2, padx=5)
bit_var = IntVar() # 여기에 int 형으로 값을 저장한다.
radio_4bit = Radiobutton(root, text="4Bit",width=3, value=4, variable=bit_var)
radio_8bit = Radiobutton(root, text="8Bit",width=3, value=8, variable=bit_var)
radio_16bit = Radiobutton(root, text="16Bit",width=3, value=16, variable=bit_var)
radio_32bit = Radiobutton(root, text="32Bit",width=3, value=32, variable=bit_var)
radio_64bit = Radiobutton(root, text="64Bit",width=3, value=64, variable=bit_var)
radio_16bit.select() # 기본값 선택
radio_4bit.grid(row=1, column=2)
radio_8bit.grid(row=2, column=2)
radio_16bit.grid(row=1, column=3)
radio_32bit.grid(row=2, column=3)
radio_64bit.grid(row=3, column=3)
btn1 = Button(root, text="실행",width=30, height=1, command=btnStart)
btn2 = Button(root, text="종료",width=30, height=1, command=btnExit)
btn1.grid(row=2, column=0, sticky=N+W+S, columnspan=1 ,padx=3, pady=3)
btn2.grid(row=2, column=1, sticky=N+W+S, columnspan=2 ,padx=3, pady=3)
label4 = Label(root, text="결과")
label4.grid(row=3, column=0,padx=5)
txtResult = Text(root, width=205, height=30)
txtResult.grid(row=4, column=0, padx=5, columnspan=10)
root.mainloop() # 마지막에 붙혀주기.
댓글남기기