#include"stdio.h"//自行判断符号
#include"math.h"//幂运算
void show(int arr[32]) {//打印输出
int i = 31;
for (i = 31; i >= 0; i--)
printf("%d", arr[i]);
}
void fun0(float x, int arr[32]) { //十进制数转换为2进制数
int i = 0;
int m=(int) x;
if (m < 0) m = -m;
while (m > 0) {
arr[i] = m % 2;
m = m / 2;
i++;
}
while (i < 31) {
arr[i] = 0;
i++;
}
}
void fun(float x ,int arr[32]) {//原码
int k = -1, i = 30;
if (x < 0) x = -x;
for (i = 30; i >= 0; i--) {
if (x >= pow(2, k)) {
arr[i] = 1; x -= pow(2, k);
}
else arr[i] = 0;
k--;
}
}
void funn(float x, int arr[32]) {
int i = 0;
if (x < 0) arr[31] = 1;//优化代码
else arr[31] = 0;
if ((-1 < x && x < 1)) fun(x, arr);
else fun0(x, arr);
for (i = 0; i < 31; i++) {
if (arr[i] == 1) arr[i] = 0;
else arr[i] = 1;
}
}
void fun1(float x) {//原码
int arr[32];
if (x < 0) arr[31] = 1;
else arr[31] = 0;
if ((-1 < x && x < 1)) fun(x, arr);
else fun0(x, arr);
show(arr);
}
void fun2(float x) {//反码
int arr[32];
funn(x, arr);
show(arr);
}
void funm(float x, int arr[32]) {
int i = 0;
funn(x, arr);
for (i = 0; i < 32; i++) {
if (arr[i] == 1) arr[i] = 0;
else {
arr[i] = 1;
break;
}
}
}
void fun3(float x) { //补码
int arr[32];
funm(x, arr);
show(arr);
}
void fun4(float x) { //移码
int arr[32];
if (x > 0) { arr[31] = 0;
if ((-1 < x && x < 1)) fun(x, arr);
else fun0(x, arr);
arr[31] = 1;
}
else{
funm(x, arr);
arr[31] = 0;}
show(arr);
}
void fun55(float x,int arr[32],int m,int e){
int k = 22,i=23;
while (m > 0) { //获取接下来8位数的阶码;
arr[i] = m % 2;
m = m / 2;
i++;
}
if (i < 30) {
for (i = i; i < 31; i++)
arr[i] = 0;
}
i = -1;
float t = x/pow(2, e)- 1;
for (k = 22; k >= 0; k--) { //获取接下来的23位尾数;
if (t >= pow(2, i)) { arr[k] = 1; t -= pow(2, i); }
else arr[k] = 0;
i--;
}
}
void fun5(float x) { //IEEE754标准化函数
int arr[32]={0}, m;
if (x > 0) arr[31] = 0;
else { arr[31] = 1; x = -x; }
int e = -126;
for (e = -126; e < 128; e++)
if (pow(2, e) <= x && x < pow(2, e + 1)) break;
m = e + 127;
fun55(x,arr,m,e);
show(arr);
}
int main() {//输出4种情况
float x,n;
printf("请输入一个数:");
scanf("%f", &x);
n=x;
int m=(int) x;
if(x==m){
if(x>0){
printf("原码表示:");fun1(x);printf("\n");
printf("反码表示:");fun1(x);printf("\n");
printf("补码表示:");fun1(x);printf("\n");
printf("移码表示:");fun4(x);printf("\n");
}
else{
printf("原码表示:");fun1(x);printf("\n");
printf("反码表示:");fun2(x);printf("\n");
printf("补码表示:");fun3(x);printf("\n");
printf("移码表示:");fun4(x);printf("\n");
}
}
else{
x-=m;
if(m>0){
printf("原码整数部分:"); fun1(m);printf(" 原码小数部分:"); fun1(x);printf("\n");
printf("反码整数部分:"); fun1(m);printf(" 反码小数部分:"); fun1(x);printf("\n");
printf("补码整数部分:"); fun1(m);printf(" 补码小数部分:"); fun1(x);printf("\n");
printf("移码整数部分:"); fun4(m);printf(" 小数部分没有移码:");printf("\n");
}
else{
printf("原码整数部分:"); fun1(m);printf(" 原码小数部分:"); fun1(x);printf("\n");
printf("反码整数部分:"); fun2(m);printf(" 反码小数部分:"); fun2(x);printf("\n");
printf("补码整数部分:"); fun3(m);printf(" 补码小数部分:"); fun3(x);printf("\n");
printf("移码整数部分:"); fun4(m);printf(" 小数部分没有移码:");printf("\n");
}
}
printf("IEEE754浮点数:");fun5(n);printf("\n");
return 0;
}
实验结论:
实验结果分析:
通过使用打印输出函数观察每种编码方式的符号位、指数位和尾数位的变化,发现:
原码:原码表示法是将一个十进制数直接转换为二进制数,符号位为0表示正数,1表示负数。
反码:反码是在原码的基础上,对负数的除符号外的所有位取反得到的数。
补码:补码是在反码的基础上加1得到的数,是计算机中常用的表示负数的方法。
移码:移码将原码的指数部分加上一个固定的偏移值,符号位为1表示正数,0表示负数。
IEEE754浮点数:IEEE754浮点数采用符号位、指数位和尾数位来表示浮点数,能够表示不同范围和精度的浮点数。
心得体会:对十进制数进行转换相对应的编码(原码,反码,补码,移码,IEEE754浮点数),是一个要实现相对应的5个功能的函数,考虑到功能之间的相互联系,先设计出相对应的框架,注意到功能之间相同的运算部分只需额外定义同一个函数,实现相应的需求时调用即可;正数的原码、反码和补码都相同,加深了对这些编码方式的理解;通过打印观察IEEE754浮点数的拆成整数部分和小数部分的表示方式,体会到其浮点数表示中的应用。
改进意见:
可以增加一些扩展的实验内容,包括浮点数运算、舍入误差分析和溢出相关问题的分析。