机器补码浮点运算(C语言实现)
计算机组成原理第二次代码作业,太抽象了这个作业
要求:使用C语言实现利用补码计算浮点数加减法
提交格式要求:
int main(){
// 使用malloc分配内存
char*xinput1 = (char*)malloc(1 * sizeof(char));
char*xinput2 = (char*)malloc(4 * sizeof(char));
char*xinput3 = (char*)malloc(1 * sizeof(char));
char*yinput1 = (char*)malloc(4 * sizeof(char));
char*yinput2 = (char*)malloc(1 * sizeof(char));
char*yinput3 = (char*)malloc(4 * sizeof(char));
// 使用 scanf 读取输入到动态分配的字符串
scanf("%s %s %s", xinput1, xinput2, xinput3);
scanf("%s %s %s", yinput1, yinput2, yinput3);
//你的代码
// 输出结果,变量仅用来展示输出格式
printf("%s,%s,%s\n", xinput1, xinput2, xinput3);
printf("%s,%s,%s\n", yinput1, yinput2, yinput3);
return 0;
}
// 样例
// 输入示例:
// 2 -011 0.101100
// 2 -010 -0.011100
// 输出示例:
// 2,-101,-0.110000
// 2,-010,0.110010
以下是代码实现。
需要注意的是,我在尾数对齐处使用真值来对齐(懒得改了),如果想要完全使用补码,稍稍更改一下line_up
函数以及调整一下与complement
函数的调用顺序即可。其次是由于老师给定了输入输出的位数,所以我在代码中有两三处直接使用了对应的数字。如果想要得到其他长度的结果,修改数字或修改函数让其接收长度均可。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 加一
void add_one(char* add){
int last = strlen(add) - 1;
add[last]++;
for (int k = last; k >= 0; k--) {
if (add[k] == '2') {
add[k] = '0';
if (k > 0 && add[k-1] != '.') {
add[k - 1] = add[k - 1] + 1;
}
}
else{
break;
}
}
}
// 加个字符
void add_fu(char* i, char fu){
int len = strlen(i);
i = realloc(i, len + 2);
memmove(i+1, i, len + 1);
i[0] = fu;
}
// 删前n个字符
void del_n(char* string, int n){
memmove(string, string + n, strlen(string));
string[strlen(string) + n - 1] = '\0';
}
// 由真值求补码
char* complement(char* real) {
int i = 0;
// 处理负数和小数
if (real[0] == '-') {
del_n(real, 1);
i = 1;
}
if (real[1] == '.') {
del_n(real, 1);
}
// 求补
int len;
switch (i){
case 0: // 非负数求补
len = strlen(real);
real = realloc(real, len + 3);
memmove(real+2, real, len + 1);
memmove(real, "00", 2);
break;
case 1: // 负数求补
for(int k = 0; k < strlen(real); k++) {
if(real[k] == '0') {
real[k]++;
}
else if(real[k] == '1') {
real[k]--;
}
}
add_one(real);
len = strlen(real);
real = realloc(real, len + 3);
memmove(real+2, real, len + 1);
memmove(real, "11", 2);
break;
default:
break;
}
return real;
}
// 传入补码,求和
char* sum(char* x, char* y){
for (int k = 0; k < strlen(x); k++) {
if (x[k] =='.') {
continue;
}
int sum = (x[k] - '0') + (y[k] - '0');
x[k] = sum + '0';
}
// 处理1+1和1+1+1的情况
int num;
for (int k = strlen(x) - 1; k >= 0; k--) {
num = 0;
if (x[k] =='.') {
continue;
}
else if (x[k] == '2') {
x[k] = '0';
num = 1;
}
else if (x[k] == '3') {
x[k] = '1';
num = 1;
}
if (k > 0 && num == 1) {
if(x[k - 1] == '.'){
x[k - 2] = x[k - 2] + 1;
}
else{
x[k - 1] = x[k - 1] + 1;
}
}
}
return x;
}
// 对齐,处理低阶数
void line_up(char* x, char* y, int number){
char zeros[number + 1];
for (int i = 0; i < number; i++) {
zeros[i] = '0';
}
zeros[number] = '\0';
int len_x = strlen(x);
int len_y = strlen(y);
x = realloc(x, len_x + number + 1);
y = realloc(y, len_y + number + 1);
// 在x后面补number个'0'
memmove(x + len_x, zeros, number);
// 在y的小数点后插入number个'0'
if(y[1] == '.'){
memmove(y + 2 + number, y + 2, len_y - 2);
memmove(y + 2, zeros, number);
}
else{
memmove(y + 3 + number, y + 3, len_y - 3);
memmove(y + 3, zeros, number);
}
x[len_x + number] = '\0';
y[len_y + number] = '\0';
}
// 补齐尾数,求和,规格化
char* sum_tail(char* x, char* y, int number){
// 对齐尾数
if (number > 0) {
line_up(x, y, number);
}
else if (number < 0) {
number = -number;
line_up(y, x, number);
}
char* com_x = complement(x);
char* com_y = complement(y);
// 求和
char* result = sum(com_x, com_y);
return result;
}
// 补码求真值
char* real(char* com){
int len;
// 如果是正数
if (com[0] == '0') {
del_n(com, 2);
if (com[0] == '.')
{
add_fu(com, '0');
}
}
// 负数:除符号位外求反,再加1,再加负号
else {
del_n(com, 2);
len = strlen(com);
// 取反
for(int k = 0; k < len; k++) {
if(com[k] == '0') {
com[k]++;
}
else if(com[k] == '1') {
com[k]--;
}
}
add_one(com);
// 补0,如果是小数的话
if (com[0] == '.')
{
len = strlen(com);
com = realloc(com, len + 2);
memmove(com+1, com, len + 1);
com[0] = '0';
}
// 加负号
add_fu(com, '-');
}
return com;
}
// 真值变号
char* change(char* y){
if(y[0] == '-') {
del_n(y, 1);
}
else {
add_fu(y, '-');
}
return y;
}
// 二进制字符串转整型
int toint(char* string){
int number;
if (string[0] == '-') {
del_n(string, 1);
number = strtol(string, NULL, 2);
number = -number;
}
else {
number = strtol(string, NULL, 2);
}
return number;
}
// 规格化,并记录偏置
void standardize(char* sum, char* i){
if (sum[0] != sum[1]) {
int len = strlen(sum);
memmove(sum + 4, sum + 3, len - 4);
sum[3] = sum[1];
sum[1] = sum[0];
add_one(i);
}
else {
int j = 0;
while(sum[3] == sum[0]){
memmove(sum + 3, sum + 4, strlen(sum) - 4);
sum[strlen(sum) - 1] = '\0';
j += 1;
add_one(i);
}
if(j != 0){
add_fu(i, '-');
sum = realloc(sum, strlen(sum) + j + 1);
int len = strlen(sum);
char zeros[j + 1];
for (int k = 0; k < j; k++) {
zeros[k] = '0';
}
zeros[j] = '\0';
memmove(sum + len, zeros, j);
}
}
sum[9] = '\0';
}
int main(){
// 使用malloc分配内存
char*xinput1 = (char*)malloc(1 * sizeof(char));
char*xinput2 = (char*)malloc(4 * sizeof(char));
char*xinput3 = (char*)malloc(10 * sizeof(char));
char*yinput1 = (char*)malloc(1 * sizeof(char));
char*yinput2 = (char*)malloc(4 * sizeof(char));
char*yinput3 = (char*)malloc(10 * sizeof(char));
char*xinput2_ = (char*)malloc(4 * sizeof(char));
char*yinput2_ = (char*)malloc(4 * sizeof(char));
char*xinput3_ = (char*)malloc(10 * sizeof(char));
char*yinput3_ = (char*)malloc(10 * sizeof(char));
// 使用 scanf 读取输入到动态分配的字符串
scanf("%s %s %s", xinput1, xinput2, xinput3);
scanf("%s %s %s", yinput1, yinput2, yinput3);
strcpy(xinput2_, xinput2);
strcpy(yinput2_, yinput2);
strcpy(xinput3_, xinput3);
strcpy(yinput3_, yinput3);
// 对阶,并转为整数存入number, order大阶
int number = toint(real(sum(complement(xinput2), complement(change(yinput2)))));
char* order;
if (number < 0){
order = yinput2_;
}
else {
order = xinput2_;
}
char* order_ = malloc(strlen(order)+1);
strcpy(order_, order);
char* i = malloc(4);
// 求和
char* sum_ = sum_tail(xinput3, yinput3, number);
strcpy(i, "000");
standardize(sum_, i);
sum_ = real(sum_);
order = real(sum(complement(order), complement(i)));
printf("%s,%s,%s\n", xinput1, order, sum_);
// 求差
char* diff = sum_tail(xinput3_, change(yinput3_), number);
strcpy(i, "000");
standardize(diff, i);
diff = real(diff);
order_ = real(sum(complement(order_), complement(i)));
printf("%s,%s,%s\n", xinput1, order_, diff);
}