机器补码浮点运算(C语言实现)

机器补码浮点运算(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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值