浮点数的加减法

 

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
//计算机组成原理作业:浮点数的加减法

//************ 二进制整数 ************
//由真值求补码(二进制整数)
void trueInt_to_twocomplement(char* bin);
//由补码求真值(二进制整数)
void twocomplementInt_to_trueInt(char* bin);
//二进制转十进制(双符号位二进制整数)
int binary_to_decimal(char* bin);
//双符号位二进制整数的加法
void add_Intbin(char* bin1, char* bin2, char* bin);

//************ 二进制小数 ************
//由真值求补码(二进制小数)
void trueDouble_to_twocomplement(char* bin);
//由补码求真值(二进制小数)
void twocomplementDouble_to_trueDouble(char* bin);
//双符号位二进制小数的加法
void add_Doublebin(char* bin1, char* bin2, char* bin);

//************ 其他 ************
//向右规格化,小数点向左移
void right_standardize(char* bin);
//向左规格化,小数点向右移, *n 用来记录小数点移动了多少位
void left_standardize(char* bin, int* n);
//对阶
void equal_exponent(char* bin, int n);
//比较两浮点数阶码,即比较 Ex 和 Ey
int compare_twocomplementInt(char* Ex_bin, char* Ey_bin);
//尾数相加
void mantissa_addition(char* Mx_bin, char* My_bin, char* bin, char* E);

//规格化数,X = Mx * 2^(Ex), Y = My * 2^(Ey)
typedef struct floatNumber
{
	char M[99];
	char E[99];
}floatNumber, *pfloatNumber;
int main() {
	//开辟内存,并给规格化数赋初值
	pfloatNumber x = (pfloatNumber)malloc(sizeof(floatNumber));
	if(x == NULL) {
		printf("分配内存失败\n");
		exit(-1);
	}
	printf("Please Enter A Value For Mx:");
	scanf("%s", &(x->M));
	printf("Please Enter A Value For Ex:");
	scanf("%s", &(x->E));

	pfloatNumber y = (pfloatNumber)malloc(sizeof(floatNumber));
	if(y == NULL) {
		printf("分配内存失败\n");
		exit(-1);
	}
	printf("Please Enter A Value For My:");
	scanf("%s", &(y->M));
	printf("Please Enter A Value For Ey:");
	scanf("%s", &(y->E));


	printf("\n---------------------------\n");
	printf("当前的规格化数 x 为:%s * 2^%s\n", x->M, x->E);
	printf("\n---------------------------\n");
	printf("当前的规格化数 y 为:%s * 2^%s\n", y->M, y->E);

	//求出 Mx,Ex,My,Ey 的补码
	 trueDouble_to_twocomplement(x->M);
	 trueInt_to_twocomplement(x->E);
	 trueDouble_to_twocomplement(y->M);
	 trueInt_to_twocomplement(y->E);

	 printf("\n---------------------------\n");
	 printf("twocomplement_Mx = %s\n", x->M);
	 printf("\n---------------------------\n");
	 printf("twocomplement_Ex = %s\n", x->E);
	 printf("\n---------------------------\n");
	 printf("twocomplement_My = %s\n", y->M);
	 printf("\n---------------------------\n");
	 printf("twocomplement_Ey = %s\n", y->E);

	 //求阶差
	 int sub_E = compare_twocomplementInt(x->E, y->E);
	 printf("\n---------------------------\n");
	 printf("sub_E = %d\n", sub_E);

	 
	 //保留大阶
	 char E[99];
	 sub_E < 0 ? strcpy(E, y->E) : strcpy(E, x->E);
	 printf("\n---------------------------\n");
	 printf("E = %s\n", E);

	 
	 //对阶
	 char twocomplement[99];
	 sub_E <= 0 ? equal_exponent(x->M, abs(sub_E)) : equal_exponent(y->M, abs(sub_E));
	 sub_E <= 0 ? strcpy(twocomplement, x->M) : strcpy(twocomplement, y->M);
	 printf("\n---------------------------\n");
	 printf("twocomplement = %s\n", twocomplement);

	 //尾数相加
	 char bin[99];
	 mantissa_addition(x->M, y->M, bin, E);
	 printf("\n---------------------------\n");
	 printf("bin = %s\n", bin);
	 printf("\n---------------------------\n");
	 printf("E = %s\n", E);

	 twocomplementInt_to_trueInt(E);
	 twocomplementDouble_to_trueDouble(bin);
	 printf("\n---------------------------\n");
	 printf("当前的规格化数 x + y 为:%s * 2^%s\n", bin, E);
	//释放内存
	free(x);
	free(y);
	
	return 0;
}

//由真值求补码(二进制整数)
void trueInt_to_twocomplement(char* bin) {
	char newBin[99];
	//原码
	char newBin1[99];
	//反码
	char newBin2[99];
	//补码
	char newBin3[99];
	//正数的原反补相同
	if (bin[0] != '-') {
		newBin[0] = newBin[1] = '0';
		int i;
		for (i = 0; i < strlen(bin); i++) {
			newBin[i + 2] = bin[i];
		}
		newBin[i + 2] = '\0';
		strcpy(bin, newBin);
	}//负数
	else {
		//原码
		newBin1[0] = newBin1[1] = '1';
		int i;
		for (i = 1; i < strlen(bin); i++) {
			newBin1[i + 1] = bin[i];
		}
		newBin1[i + 1] = '\0';
		newBin2[0] = newBin2[1] = '1';
		for (i = 2; i < strlen(newBin1); i++) {
			newBin2[i] = newBin1[i] == '0' ? '1' : '0';
		}
		newBin2[i] = '\0';
		for (int i = 0; i < strlen(newBin2); i++) {
			newBin3[i] = newBin2[i];
		}
		newBin3[strlen(newBin2)] = '\0';
		//bool 用于判断有没有进行进位操作
		//0 表示未进位,1 表示进位操作已完成,退出循环
		int bool = 0;
		for (int i = strlen(newBin2) - 1; i >= 2 && bool == 0; i--) {
			//如果当前位为 0 的话,直接进位就行,并把 bool 改成 1,完成进位操作,退出循环
			if (newBin2[i] == '0') {
				newBin3[i] = '1';
				bool = 1;
			}//如果当前为为 1 的话,当前位变为 0,向下一位进 1,继续循环
			else {
				newBin3[i] = '0';
			}
		}
		//反码是 111 这种情况,说明真值为 0,0 的补码是 0
		if (bool == 0) {
			return "0";
		}
		else {
			strcpy(bin, newBin3);
		}
	}
}

//由真值求补码(二进制小数)
void trueDouble_to_twocomplement(char* bin) {
	char newBin[99];
	//原码
	char newBin1[99];
	//反码
	char newBin2[99];
	//补码
	char newBin3[99];
	//正数的原反补相同
	if (bin[0] != '-') {
		newBin[0] = newBin[1] = '0';
		int i;
		for (i = 1; i < strlen(bin); i++) {
			newBin[i + 1] = bin[i];
		}
		newBin[i + 1] = '\0';
		strcpy(bin, newBin);
	}//负数
	else {
		//原码
		newBin1[0] = newBin1[1] = '1';
		int i;
		for (i = 2; i < strlen(bin); i++) {
			newBin1[i] = bin[i];
		}
		newBin1[i] = '\0';
		newBin2[0] = newBin2[1] = '1';
		newBin2[2] = '.';
		for (i = 3; i < strlen(newBin1); i++) {
			newBin2[i] = newBin1[i] == '0' ? '1' : '0';
		}
		newBin2[i] = '\0';
		for (int i = 0; i < strlen(newBin2); i++) {
			newBin3[i] = newBin2[i];
		}
		newBin3[strlen(newBin2)] = '\0';
		//bool 用于判断有没有进行进位操作
		//0 表示未进位,1 表示进位操作已完成,退出循环
		int bool = 0;
		for (int i = strlen(newBin2) - 1; i >= 3 && bool == 0; i--) {
			//如果当前位为 0 的话,直接进位就行,并把 bool 改成 1,完成进位操作,退出循环
			if (newBin2[i] == '0') {
				newBin3[i] = '1';
				bool = 1;
			}//如果当前为为 1 的话,当前位变为 0,向下一位进 1,继续循环
			else {
				newBin3[i] = '0';
			}
		}
		//真值为 0,0 的补码是 0
		if (bool == 0) {
			return "0";
		}
		else {
			strcpy(bin, newBin3);
		}
	}
}

//由补码求真值(二进制整数)
void twocomplementInt_to_trueInt(char* bin) {
	//newBin 字符数组用来存放真值
	char newBin[99];
	char newBin1[99];
	char newBin2[99];
	//补码为 0
	if (strlen(bin) == 1 && bin[0] == '0') {
		return "0";
	}
	//正数的原反补相同
	if(bin[0] == '0' && bin[1] == '0') {
		int i;
		for (i = 2; i < strlen(bin); i++) {
			newBin[i - 2] = bin[i];
		}
		newBin[i - 2] = '\0';
	}
	else {
		newBin[0] = '-';
		//先直接去除符号位(暂时不考虑符号位后面的变化)
		int i;
		for (i = 2; i < strlen(bin); i++) {
			newBin1[i - 2] = bin[i];
		}
		newBin1[i - 2] = '\0';
		//可以判断有没有遇到 1,遇到 1 的话直接退出循环
		int bool = 0;
		for (i = strlen(newBin1) - 1; i >= 0 && bool == 0; i--) {
			if (newBin1[i] == '1') {
				newBin2[i] = '0';
				bool = 1;
			}
			else {
				newBin2[i] = '1';
			}
		}
		//中途碰到 1 
		if (bool == 1) {
			for (int j = 0; j <= i; j++) {
				newBin2[j] = newBin1[j];
			}
		}
		newBin2[strlen(newBin1)] = '\0';
		//按位取反就是真值 
		for (i = 0; i < strlen(newBin2); i++) {
			newBin[i + 1] = newBin2[i] == '0' ? '1' : '0';
		}
		newBin[i + 1] = '\0';
	}
	strcpy(bin, newBin);
}

//由补码求真值(二进制小数)
void twocomplementDouble_to_trueDouble(char* bin) {
	//newBin 字符数组用来存放真值
	char newBin[99];
	char newBin1[99];
	char newBin2[99];
	//补码为 0
	if (strlen(bin) == 1 && bin[0] == '0') {
		return "0";
	}
	
	//正数的原反补相同
	if (bin[0] == '0' && bin[1] == '0') {
		int i;
		for (i = 1; i < strlen(bin); i++) {
			newBin[i - 1] = bin[i];
		}
		newBin[i - 1] = '\0';
	}
	else {
		newBin[0] = '-';
		newBin[1] = '0';
		newBin[2] = '.';
		//先直接去除符号位(暂时不考虑符号位后面的变化)
		int i;
		for (i = 3; i < strlen(bin); i++) {
			newBin1[i - 3] = bin[i];
		}
		newBin1[i - 3] = '\0';
		//可以判断有没有遇到 1,遇到 1 的话直接退出循环
		int bool = 0;
		for (i = strlen(newBin1) - 1; i >= 0 && bool == 0; i--) {
			if (newBin1[i] == '1') {
				newBin2[i] = '0';
				bool = 1;
			}
			else {
				newBin2[i] = '1';
			}
		}
		//中途碰到 1 
		if (bool == 1) {
			for (int j = 0; j <= i; j++) {
				newBin2[j] = newBin1[j];
			}
		}
		newBin2[strlen(newBin1)] = '\0';
		//按位取反就是真值 
		for (i = 0; i < strlen(newBin2); i++) {
			newBin[i + 3] = newBin2[i] == '0' ? '1' : '0';
		}
		newBin[i + 3] = '\0';
	}
	strcpy(bin, newBin);
}

//二进制转十进制(双符号位二进制整数)
int binary_to_decimal(char* bin) {
	int res;
	res = 0;
	int exponent = strlen(bin) - 3;
	for (int i = 2; i < strlen(bin); i++, exponent--) {
		res = bin[i] == '0' ? res : res + pow(2, exponent);
	}
	return bin[0] == '0' ? res : 0 - res;
}

//比较两浮点数阶码,即比较 Ex 和 Ey
int compare_twocomplementInt(char* Ex_bin, char* Ey_bin) {
	int decimal_Ex = binary_to_decimal(Ex_bin);
	int decimal_Ey = binary_to_decimal(Ey_bin);
	return decimal_Ex - decimal_Ey;
}

//双符号位二进制整数的加法
void add_Intbin(char* bin1, char* bin2, char* bin) {
	char newBin1[99];
	char newBin2[99];
	char newBin3[99];
	int length = max(strlen(bin1), strlen(bin2));
	//使位数与位数大的保持一致(即位数小的前面补 0,便于后面加法运算)
	int i,j;
	for (i = 0; i < length; i++) {
		newBin1[i] = bin1[i] == '1' ? '1' : '0';
		newBin2[i] = bin2[i] == '1' ? '1' : '0';
	}
	newBin1[length] = newBin2[length] = '\0';
	if (length == strlen(bin1)) {
		for (i = 2; i < 2 + strlen(bin1) - strlen(bin2); i++) {
			newBin2[i] = newBin2[0] == '0' ? '0' : '1';
		}
		for (i = strlen(bin2), j = 2; i < strlen(bin1); i++,j++) {
			newBin2[i] = bin2[j];
		}
	}
	else if (length == strlen(bin2)) {
		for (i = 2; i < 2 + strlen(bin2) - strlen(bin1); i++) {
			newBin1[i] = newBin1[i] == '0 ' ? '0' : '1';
		}
		for (j = 2; i < strlen(bin2); i++, j++) {
			newBin1[i] = bin1[j];
		}
	}
	printf("newBin1 = %s\n", newBin1);
	printf("newBin2 = %s\n", newBin2);

	// bool 的值为 0,表示没有进位, bool 的值为 1,表示有进位
	int bool = 0;
	for (i = strlen(newBin1) - 1; i >= 0; i--) {
		if (newBin1[i] == '0' && newBin2[i] == '0') {
			newBin3[i] = bool == 0 ? '0' : '1';
			bool = 0;
		}
		else if ((newBin1[i] == '0' && newBin2[i] == '1') || (newBin1[i] == '1' && newBin2[i] == '0')) {
			newBin3[i] = bool == 0 ? '1' : '0';
		}
		else if (newBin1[i] == '1' && newBin2[i] == '1') {
			newBin3[i] = bool == 0 ? '0' : '1';
			bool = 1;
		}
	}
	newBin3[strlen(newBin1)] = '\0';
	printf("newBin3 = %s\n", newBin3);
	strcpy(bin, newBin3);
}

//双符号位二进制小数的加法
void add_Doublebin(char* bin1, char* bin2, char* bin) {
	char newBin1[99];
	char newBin2[99];
	char newBin3[99];
	char newBin4[99];
	int length = max(strlen(bin1), strlen(bin2));
	int i;
	//去掉小数点,并且使位数与位数大的保持一致(即位数小的后面补 0,便于后面加法运算)
	for (i = 0; i < 2; i++) {
		newBin1[i] = bin1[i];
		newBin2[i] = bin2[i];
	}
	for (i = 3; i < length; i++) {
		newBin1[i - 1] = bin1[i] == '1' ? '1' : '0';
		newBin2[i - 1] = bin2[i] == '1' ? '1' : '0';
	}
	newBin1[i - 1] = newBin2[i - 1] = '\0';
	// bool 的值为 0,表示没有进位, bool 的值为 1,表示有进位
	int bool = 0;
	for (i = strlen(newBin1) - 1; i >= 0; i--) {
		if (newBin1[i] == '0' && newBin2[i] == '0') {
			newBin3[i] = bool == 0 ? '0' : '1';
			bool = 0;
		}
		else if ((newBin1[i] == '0' && newBin2[i] == '1') || (newBin1[i] == '1' && newBin2[i] == '0')) {
			newBin3[i] = bool == 0 ? '1' : '0';
		}
		else if (newBin1[i] == '1' && newBin2[i] == '1') {
			newBin3[i] = bool == 0 ? '0' : '1';
			bool = 1;
		}
	}
	newBin3[strlen(newBin1)] = '\0';
	for (i = 0; i < 2; i++) {
		newBin4[i] = newBin3[i];
	}
	newBin4[2] = '.';
	for (i = 2; i < strlen(newBin3); i++) {
		newBin4[i + 1] = newBin3[i];
	}
	newBin4[i + 1] = '\0';

	strcpy(bin, newBin4);
}

//尾数相加
void mantissa_addition(char* Mx_bin, char* My_bin, char* bin, char* E) {
	add_Doublebin(Mx_bin, My_bin, bin);
	//规格化:
	//		采用双符号位的补码: S = 00.1xxx xxxx...
	//							 S = 11.0xxx xxxx...
	//若不是规格化的数,需要尾数向左移动,以实现规格化,即向左规格化
	//如果尾数相加发生正溢或负溢,即S = 01.xxxx xxxx...或S = 10.xxxx xxxx...,向右规格化
	if ((bin[0] == '0' && bin[1] == '1') || (bin[0] == '1' && bin[1] == '0')) {
		right_standardize(bin);
		char newBin[99];
		add_Intbin(E, "001", newBin);
		strcpy(E, newBin);
	}
	else {
		char newBin[99];
		char newBin1[99];
		newBin1[0] = '-';
		int n;
		left_standardize(bin, &n);
		printf("n = %d\n", n);
		itoa(n, newBin, 2);
		printf("newBin = %s\n", newBin);
		int i;
		for (i = 0; i < strlen(newBin); i++) {
			newBin1[i + 1] = newBin[i];
		}
		newBin1[i + 1] = '\0';
		printf("newBin1 = %s\n", newBin1);
		trueInt_to_twocomplement(newBin1);
		printf("newBin1 = %s\n", newBin1);
		add_Intbin(E, newBin1, newBin);
		strcpy(E, newBin);
	}
}	

//对阶
void equal_exponent(char* bin, int n) {
	char newBin[99];
	int i;
	for (i = 0; i < 3; i++) {
		newBin[i] = bin[i];
	}
	for (i = 3; i < n + 3; i++) {
		newBin[i] = '0';
	}
	for (i = 3; i < strlen(bin); i++) {
		newBin[i + n] = bin[i];
	}
	newBin[i] = '\0';
	strcpy(bin, newBin);
}

//向右规格化,小数点向左移
void right_standardize(char* bin) {
	char newBin[99];
	newBin[0] = newBin[1] = bin[0];
	newBin[2] = '.';
	newBin[3] = bin[1];
	int i;
	for (i = 3; i < strlen(bin); i++) {
		newBin[i + 1] = bin[i];
	}
	newBin[i] = '\0';
	strcpy(bin, newBin);
}

//向左规格化,小数点向右移, *n 用来记录小数点移动了多少位
void left_standardize(char* bin, int* n) {
	static char newBin[99];
	memset(newBin, '\0', sizeof(newBin));
	char newBin1[99];
	//去掉小数点
	newBin1[0] = newBin1[1] = bin[0];
	for (int i = 3; i < strlen(bin); i++) {
		newBin1[i - 1] = bin[i];
	}
	newBin1[strlen(bin) - 1] = '\0';
	int index = 0;
	//如果符号位是 11,寻找第一个 0,如果符号位是 00,寻找第一个 1
	char c = bin[0] == '0' ? '1' : '0';
	for (int i = 0; i < strlen(newBin1); i++) {
		//找到目标,index 记录对应的索引位置,结束for循环
		if (newBin1[i] == c) {
			index = i;
			break;
		}
	}
	newBin[0] = newBin1[index - 2];
	printf("newBin[0] = %c\n", newBin[0]);
	newBin[1] = newBin1[index - 1];
	newBin[2] = '.';
	int i, j;
	for (i = index, j = 3; i < strlen(newBin1); i++,j++) {
		newBin[j] = newBin1[i];
	}
	newBin[j] = '\0';
	*n = index - 2;
	strcpy(bin, newBin);
}

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值