上一篇文章http://blog.csdn.net/tina224243/article/details/51919993,通过直接读取float的地址显示出二进制码。
float的存储分为指数部分和小数部分两部分存储,本文将通过flotat的存储原理计算出二进制码,以及由二进制码反转显示float值;
参考:http://blog.csdn.net/nethibernate/article/details/6120382
总结一下,实数转二进制float类型的方法:
A. 分别将实数的整数和小数转换为二进制
B. 左移或者右移小数点到第一个有效数字之后
C. 从小数点后第一位开始数出23位填充到尾数部分
D. 把小数点移动的位数,左移为正,右移为负,加上偏移量127,将所得的和转换为二进制填充到指数部分
E. 根据实数的正负来填充符号位,0为正,1为负
如果需要把float的二进制转换回十进制的实数,只要将上面的步骤倒着来一边就行了。
// float转二进制,二进制转float,方法一:
#include "stdafx.h"#include <string.h>#include <math.h>// 反向输出字符串;char* back(char* in)
{
int len = strlen(in);
char* out = newchar[len + 1];
for (int i = len - 1; i >= 0; i--)
{
out[len -1 - i] = in[i];
}
out[len] = '\0';
return out;
}
// 整数转二进制;char* int2b(int ni)
{
int r = 0, count = 0;
char* fint = NULL;
char* temp = newchar[32];
do{
r = ni % 2;
ni = ni / 2;
*temp++ = r + '0';
count++;
}while (ni > 0);
*temp = '\0';
printf("temp:%s\n", temp - count);
fint = back(temp - count);
printf("fint:%s\n", fint);
delete [] (temp - count);
return fint;
}
// 小数转二进制;char* frac2b(float nf, int Lnf)
{
int r = 0, count = 0;
char* ffrac = newchar[Lnf + 1];
do
{
nf = nf * 2;
r = int(nf);
*ffrac++ = r + '0';
nf = nf - r;
count++;
}while(nf != 0 && (--Lnf) > 0);
*ffrac = '\0';
printf("ffrac:%s\n", ffrac - count);
return ffrac - count;
}
// 整数部分为0时,偏移量int expcount(char* frac2b)
{
char* temp = frac2b;
int count = 0;
while (*temp++ != '1')
{
++count;
}
return count + 1;
}
// 整数部分为0时,小数部分右移char* frac2b0(int ecount, char* frac2b)
{
char* ffrac0 = newchar[24];
int len = strlen(frac2b);
int i = 0;
for (i = ecount; i < len; i++)
{
ffrac0[i - ecount] = frac2b[i];
}
ffrac0[i - ecount] = '\0';
printf("ffrac0:%s\n", ffrac0);
return ffrac0;
}
// 指数;char* exp2b(int Lne)
{
char* fexp0 = newchar[9];
int offset = Lne + 127;
char* fexp = int2b(offset);
int lfexp = strlen(fexp); // 判断指数长度,不足8位补0;if (lfexp < 8)
{
fexp0[0] = '0';
fexp0[1] = '\0';
strcat(fexp0, fexp);
printf("fexp0:%s\n", fexp0);
delete [] fexp;
return fexp0;
}
else
{
printf("fexp:%s\n", fexp);
delete [] fexp0;
return fexp;
}
}
// 整数部分,二进制转十进制int bintodec(char* pbin)
{
char* temp = pbin;
int len = strlen(temp);
int binary = 0;
for (int i = 0; i < len; i++)
{
int n = temp[i] - '0';
binary += n << (len - 1 - i);
}
return binary;
}
// 逆运算// 小数部分,二进制转十进制float bintodec2(char* pbin)
{
char* temp = pbin;
int len = strlen(temp);
float fbinary = 0.;
for (int i = 0; i < len; i++)
{
int n = temp[i] - '0';
fbinary += n / pow(2.0, 1.0 + i);
}
return fbinary;
}
// 二进制转floatvoid bin2float(char* bs)
{
char* bexps = newchar[9]; // 指数部分float n = 0.;
// 计算偏移量for (int i = 0; i < 8; i++)
{
bexps[i] = bs[i + 1];
}
bexps[8] = '\0';
int bexp = bintodec(bexps);
if (bexp == 0)
{
printf("hahaha:%s = %f\n", bs, "0.00");
}
else
{
int offset = bexp - 127;
if (offset < 0)
{
float bint0 = 0.; // 整数部分char* bfracs = newchar[24]; // 小数部分int offset0 = abs(offset);//偏移量char* temp = newchar[24];
// 计算小数for (int i = 0; i < 23; i++)
{
bfracs[i] = bs[i + 9];
}
bfracs[23] = '\0';
// 恢复去掉的0....01for (int i = 0; i < offset0 - 1; i++)
{
temp[i] = '0';
}
temp[offset0-1] = '1';
temp[offset0] = '\0';
strncat(temp, bfracs, 23 - offset0);
float bfrac = bintodec2(temp);
n = bint0 + bfrac;
delete [] bfracs;
delete [] temp;
}
else
{
char* bints = newchar[offset + 2]; // 整数部分char* bfracs = newchar[24 - offset]; // 小数部分// 计算整数
bints[0] = '1';// 整数补1;for (int i = 1; i <= offset; i++)
{
bints[i] = bs[i + 8];
}
bints[offset + 1] = '\0';
int bint = bintodec(bints);
// 计算小数for (int i = 0; i < 23 - offset; i++)
{
bfracs[i] = bs[i + 9 + offset];
}
bfracs[23 - offset] = '\0';
float bfrac = bintodec2(bfracs);
n = (float)bint + bfrac;
delete [] bints;
delete [] bfracs;
}
if (bs[0] == '1')
n = 0.0 - n;
printf("hahaha:%s = %f\n", bs, n);
}
delete [] bexps;
}
void main()
{
float orign = 0.;
char* fint = NULL;
char* ffrac = NULL;
char* fexp = NULL;
printf("Enter a float number.\n");
while (scanf("%f", &orign) == 1)
{
char* fbit = newchar[33];
float n = abs(orign); // 先按正数计算 int ni = int(n); // 整数float nf = n - ni; // 小数
fint = int2b(ni); // 计算整数// 判断符号位,输入是否为0;if (orign == 0.)
{
for (int i = 0; i < 32; i++)
{
fbit[i] = '0';
}
fbit[32] = '\0';
printf("%.3f = %s\n", orign, fbit);
bin2float(fbit);// 逆计算printf("Enter a float number.\n");
delete [] fbit;
delete [] fint;
continue;
}
elseif (orign < 0)
fbit[0] = '1';
else
fbit[0] = '0';
fbit[1] = '\0';
int Lni = strlen(fint);
int Lnf = 24 - Lni; // 需要计算的小数位数int Lne = Lni -1; // 偏移量
ffrac = frac2b(nf, Lnf); // 计算小数char* ffrac00 = NULL;
if (n < 1)
{
int ecount = expcount(ffrac);
ffrac00 = frac2b0(ecount, ffrac);
fexp = exp2b(-ecount);
// 符号位+指数位+小数位strcat(fbit, fexp);
printf("singnal+fexp :%s\n", fbit);
strcat(fbit, ffrac00);
printf("singnal+fexp+fint+ffrac:%s\n", fbit);
delete [] ffrac00;
}
else
{
fexp = exp2b(Lne); // 计算指数// 符号位+指数位+小数位strcat(fbit, fexp);
printf("singnal+fexp :%s\n", fbit);
strcat(fbit, fint + 1);
printf("singnal+fexp+fint :%s\n", fbit);
strcat(fbit, ffrac);
printf("singnal+fexp+fint+ffrac:%s\n", fbit);
}
// 小数位,不足23位的补0;int len = strlen(fbit);
if (len < 32)
{
for (int i = 0; i < 32-len; i++)
fbit[len + i] = '0';
}
fbit[32] = '\0';
printf("%.3f = %s\n", orign, fbit);
bin2float(fbit);// 逆计算delete [] fint;
delete [] ffrac;
delete [] fbit;
delete [] fexp;
printf("Enter a float number.\n");
}
}
// 方法二:
// 暂不考虑负数// 1 符号// 8 指数 + 127// 23 尾数 0.xxxxxxxconststaticint LEN = 32;
// 整数转二进制void int2b(int n, char* out)
{
char* p = out;
if (n == 0)
{
out[0] = '0';
return;
}
while (true)
{
int k = n / 2;
int j = n % 2;
*p++ = '0' + j;
if (k == 0)
break;
n = k;
}
// 逆向
size_t len = strlen(out);
char* temp = newchar[len + 1];
for (size_t i = 0; i < len; ++i)
{
temp[i] = out[len - i - 1];
}
temp[len] = '\0';
strcpy(out, temp);
delete[] temp;
}
// 小于1的浮点数转二进制// 可能是无限小数// 这里最多32位void dec2b(double f, char* out)
{
char* p = out;
while (p - out < LEN)
{
f *= 2;
int n = (int)f; // 整数部分
*p++ = '0' + n;
f -= n;
if (f == 0)
{
break;
}
}
}
// 参数之所以用double// 用float有效数字太少,计算含误差char* dec2b(double d)
{
// 得到整数部分char nout[LEN + 1] = { 0 };
int n = (int)d;
int2b(n, nout);
// 小数部分double d2 = d - n;
char dout[LEN + 1] = { 0 };
dec2b(d2, dout);
// 计算尾数
size_t nlen = strlen(nout);
char end[24] = { 0 };
char* p = end;
// 前半部分for (size_t i = 1; i < nlen; ++i)
{
*p++ = nout[i];
}
// 后半部分
size_t dlen = strlen(dout);
size_t rlen = 23 - (nlen - 1); // 尾数剩余空间if (dlen > rlen)
{
dlen = rlen;
}
for (size_t i = 0; i < dlen; ++i)
{
*p++ = dout[i];
}
// 计算指数char power[9] = { 0 };
int temp = 127 + nlen - 1;
int2b(temp, power);
// 结果char* res = newchar[LEN + 1];
p = res;
// 符号
*p++ = '0';
// 指数memcpy(p, power, 8 * sizeof(char));
p += 8 * sizeof(char);
// 尾数memcpy(p, end, 23 * sizeof(char));
res[LEN] = '\0';
return res;
}
int main()
{
char* res = dec2b(6.9);
printf(res);
printf("\n");
delete[] res;
return0;
}