1. 实验要求
用C/C++编程实现两个十进制整数(将其转换成原码)乘法运算结果,提示思想:原码一位乘
2. 相关知识点
机器字长全部假设为 8 位,只讨论整数,后不再特殊说明
0. 移位
再次回忆原码的移位:左移右移都是符号位不变,数值位补“0”
1. 符号位
- 符号位取 1 位,0 为正,1 为负
- 符号位不直接参与乘法运算
- 结果的符号位 = 乘数符号位 ⊕ 被乘数符号位
2. 数值部分
-
操作数取绝对值
-
被乘数 x 乘数 = 积
-
部分积 = 两位全 0 符号位(高位) 拼接 全 0 被乘数数值位(低位)
-
积 = 部分积(高位) 拼接上 乘数的数值位(低位)
-
令乘数的最低位为判断位,若为 1,则加被乘数,否则加 0
-
累加后积右移一位,挤走乘数的最低位
-
重复上两步加和移位的操作,直到乘数的所有位全部被判断过(即乘数的数值部分有几位,就加、移位几次)
3. 实现思路
0. 准备
包括:
- 检查输入是否合法,即第一个输入为"+“或”-",其后输入为数字
- 确定输入十进制的正负
- 将输入的 string 转换为 int 类型
1. 转二进制
由准备工作准备好的 int 类型的数字直接转换为二进制,不过要注意两点,一是当数字为 0 时,取不到值,这时我们自己手动添个 0 上去,二是当数字为负数时,结果就很迷…解决方法是用其他变量暂存数字的绝对值
2. 转原码
由于取的全是绝对值,且积和乘数被乘数数值位数有关,所以原码就是二进制,不用再额外加 0
3. 计算
简化来看,原码一位乘就是循环的两个步骤,相加求和,移位
4. 相加求和
每次对 C 的最后一位进行判断,如果是 1,就 + A 一次,否则 + 0,同时更新 A 的值,并打印
5. 移位
移位操作也分两步,首先把 A 的最后一位插入到 C 的首位,截取 C 的总位数 - 1,得到 C 的移位结果,再把 A 的符号位之后插 0,截取 A 的总位数 -1,得到 A 的移位结果
4. 具体实现
#include<iostream>
#include<cmath> //abs
#include<malloc.h> //malloc
#include<algorithm> // reverse
#include<string> // string
#include<sstream> // stringstream
#include<cmath> // pow
#include "windows.h"
#define PLUS 1 // 正
#define MINUS -1 // 负
#define SYMBOLNUM 1 // 符号位长度
#define WORD_LENGTH 8 // 机器字长
#define MIN (-(1<<(WORD_LENGTH-SYMBOLNUM))+1) // 最小取值范围,注意取不到 -2^(n-1)了
#define MAX ((1<<(WORD_LENGTH-SYMBOLNUM))-1) // 最大取值范围
using namespace std;
typedef struct Integer *Number;
struct Integer{
// 定义一个结构体,把该数的各种码放进去
string input; // 输入的带符号十进制整数
string binary; // 二进制真值
string yuan_code; // 原码
int symbol; // 符号位
int decimal; // 十进制整数
};
/* 准备工作
1.检查输入是否合法
2.确定输入十进制数的正负
3.将 string 类型转换成 int 类型
4.确定输入十进制数的范围
*/
void prepare(Number num){
// 验证输入合法性,确定该十进制整数的正负
for(int i=0;i<(num->input.size());i++){
if(num->input[0]=='+' && !i){
// 如果第一个字符为 +
num->symbol = PLUS; // 记录符号为 +
}else if(num->input[0]=='-' && !i){
//如果第一个字符为 -
num->symbol = MINUS; // 记录符号为 -
}else if(!((num->input[i]>='0' || num->input[i]<='9') && i)){
// 如果不是第一个字符,且不在 0~9 之间
cout<<"输入不合法,请重新启动!\n"<<endl;
exit(0); // 提示并结束程序
}
}
// 转换输入十进制整数的类型
stringstream