计算机系统基础:实验3 同符号浮点数加法运算/无符号定点数乘法运算的机器级表示
提示:根据《计算机系统基础》 中给出的解释来解决更容易,看一下p73页能更简单理解
题目要求:
- 能够用C语言仿真浮点数加法器的运算过程
- 能够用C语言仿真无符号数乘法器的运算过程
#include <stdio.h>
#include <stdlib.h>
float addfloat(char float1[], char float2[], int m, int n);
unsigned mul(char int1[], char int2[], int m, int n);
float floatToValue(char binary[],int count);//浮点数的10进制转换
int calExponent(char float1[], char float2[]);//对阶
int shiftRight(char wei1_re[]);// 计算右规
void unsignedAdd(char wei1[],char wei2[],char wei_re[]);//计算无符号数相加
int main(){
// 浮点数加法器
// char float1[33];
// char float2[33];
// printf("浮点数:\n");
// fgets(float1,33,stdin);
// scanf("\n");
// fgets(float2,33,stdin);
// int m = 0,n = 0;
// float result = addfloat(float1,float2,m,n);
// printf("结果为:%f \n",result);
//无符号整数乘法
char int1[5];
char int2[5];
printf("乘法:\n");
fgets(int1,5,stdin);
scanf("\n");
fgets(int2,5,stdin);
int m = 0,n = 0;
mul(int1, int2,m,n);
return 0;
}
float addfloat(char float1[], char float2[], int m, int n){
char wei1[27],wei2[27],wei_re[27],result[32];;
int i;
for(i=0;i<27;i++){
wei1[i] = '0';
wei2[i] = '0';
wei_re[i] = '0';
}
int move = calExponent(float1, float2);
//尾数加减
if(move<0){
//move = -move;
int t;
//27位中第零位不取数字,用作进位
//第二位为隐藏位,必为‘1’
wei1[-move+1] = '1';
wei2[1] = '1';
//之后的的23位为尾数的小数值
for(t=9;t<32;t++){
wei1[t-7-move] = float1[t];
wei2[t-7] = float2[t];
}
unsignedAdd(wei1, wei2, wei_re);
//右规
int count = shiftRight(wei_re);
//计算最终值
for (i = 0; i<32; i++) {
if(i<9){
result[i] = float2[i];
}
else{
result[i] = wei_re[i-7];//结果尾数的从第2位开始 第0位是右规 第1位是隐藏位
}
}
return floatToValue(result,count);
}
else{
int t;
//27位中第零位不取数字,用作进位
//第二位为隐藏位,必为‘1’
wei2[move+1] = '1';
wei1[1] = '1';
//之后的的23位为尾数的小数值
for(t=9;t<32;t++){
wei2[t-7+move] = float2[t];
wei1[t-7] = float1[t];
}
unsignedAdd(wei2, wei1, wei_re);
//右规
int count = shiftRight(wei_re);
//计算最终值
for (i = 0; i<32; i++) {
if(i<9){
result[i] = float1[i];
}
else{
result[i] = wei_re[i-7];//结果尾数的从第2位开始 第0位是右规 第1位是隐藏位
}
}
return floatToValue(result,count);
}
}
//计算阶码
int calExponent(char float1[], char float2[]){
int count=0,i,j,e1=0,e2=0;
char temp[9];
temp[0] = '0';
//对阶 float1的阶码-float2的阶码
for(i = 8; i >= 1; i--) {
if(count){
temp[i] = float2[i]=='1' ? '0':'1';
}
if(float2[i]!='0'&& count == 0){
temp[i] = float2[i];
count++;
}
}
for(j=1;j<9;j++){
if(float1[j]=='1') {
e1 = e1 + (1<<(8-j));
}
if(temp[j]=='1') {
e2 = e2 + (1<<(8-j));
}
}
return e1+e2-256;
}
//尾数右移
int shiftRight(char wei_re[]){
//右规
int count = 0;
if (wei_re[0] == '1') {
int i;
count++;
char temp[27];
for (i=0; i<27; i++) {
temp[i] = wei_re[i];
}
wei_re[0] = '0';
for (i = 1; i<27; i++) {
wei_re[i] = i==0 ? 0:temp[i-1];
}
}
if(wei_re[26]=='1'){
if(wei_re[25]=='1'){
int t;
for (t = 24; t>=0; t++) {
if(wei_re[t]!='1'){
wei_re[t] = '1';
break;
}
wei_re[t] = '0';
}
}
else {
if(wei_re[24]=='1'){
int v;
for (v = 23; v>=0; v++) {
if(wei_re[v]!='1'){
wei_re[v] = '1';
break;
}
wei_re[v] = '0';
}
}
}
}
return count;
}
//无符号数增加
void unsignedAdd(char wei1[],char wei2[],char wei_re[]){
char carr='0';
int j;
for(j=26;j>=1;j--){
if(wei1[j] == '1'&&wei2[j] == '1'){
if(carr=='1'){
wei_re[j]='1';
}else{
wei_re[j]='0';
}
carr='1';
}else if (wei1[j] == '0'&&wei2[j] == '0'){
if(carr=='1'){
wei_re[j]='1';
}else{
wei_re[j]='0';
}
carr='0';
}else {
if(carr=='1'){
wei_re[j]='0';
}else{
wei_re[j]='1';
}
}
}
//此处判断结果尾数是否需要进位
if(carr=='1'){
wei_re[0] = '1';
}
}
//浮点数转10进制
float floatToValue(char binary[],int count){
float sum = 0;
int exponent = 0;
int symbol = 1;
float significand = 0;
if(binary[0]=='1') {
symbol = -1;//符号位
}
for(int i = 1; i < 9; i++) {
if(binary[i]=='1') {
exponent = exponent + (1<<(8-i));
}
}
//此处判断是否存在右规行为 有的话阶码加一 没有的话照旧
exponent = count<=0 ? exponent - 127:exponent - 126 ;//所得阶码减去偏移量
if(exponent>=0) {
significand = 1<<exponent;
for(int i = 9; i < 32; i++) {
if(binary[i]=='1') {
//此处计算小数点前的位数
if(exponent > i-9){
significand = significand + (1<<(exponent-(i-8)));
}else{
//此处计算小数点后的位数
significand = significand + (1.0/(1<<(i-exponent-8)));
}
}
}
sum = significand * symbol;
} else {
for(int i = 9; i < 32; i++) {
if(binary[i]=='1') {
significand = significand + (1.0/(1<<(exponent+i-8)));
}
sum = significand * symbol;
}
}
if((exponent==128)&&(significand==0)) {
printf("无穷大\n");
return (1.0/0.0);//表示无穷
}
if((exponent==128)&&(significand!=0)) {
printf("非规格化数正上溢\n");
return (0.0/0.0);//不是一个数字
}
if((exponent==-127)&&(significand!=0)) {
printf("非规格化数正下溢\n");
return 0;
}
return sum;
}
//无符号整数乘法
unsigned mul(char int1[], char int2[], int m, int n){
char result[9];
for (m = 0; m<9; m++) {
result[m] = '0';
}
int count = 8;
char cin = '0';
for (n = 3; n>0; n--) {
if(int2[n]!='0'){
int i,j = count;
for(i = 3 ;i>=0;i--){
if(int1[i] == result[j]){
char temp = result[j];
result[j] = cin!='0' ? '1':'0';
cin = temp!='0' ? '1':'0';
}else{
result[j] = cin!='0' ? '0':'1';
cin = result[j] !='0' ? '0':'1';
}
j--;
}
}
count--;
}
printf("结果为:");
for (n = 1; n<9; n++) {
printf("%c",result[n]);
if (n==4) {
printf(" ");
}
}
return 0;
}
测试举例:
总结:
秘诀:一定要看书,一定要看书!!
那什么我C语言基础比较差,所以这个整了一周才完成,但是还是很有成就感的,哈哈哈哈哈哈,加油各位!