c语言、浮点数怎么变成16进制
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言、浮点数怎么变成16进制相关的知识,希望对你有一定的参考价值。
浮点数2.5的十六进制格式为0×40200000。。。。这个怎么转换过来的。。。。有点看不懂
数据类型的作用是说明数据和操作的意义,换句话说给定一块内存,可以说它是int类型,也可以说它是float类型。
同时C语言中输出十六进制数,必须是整型数,因此,可以使用union联合体来输出浮点数的16进制。示例代码如下:
#include <stdio.h>union fi
float f;
int i;
ufi;
int main()
ufi.f = 1.1f;
printf("%x\\n", ufi.i );
参考技术A
需要准备的材料分别有:电脑、C语言编译器。
1、首先,打开C语言编译器,新建一个初始.cpp文件,例如:test.cpp。
2、在test.cpp文件中,输入C语言代码:printf("%x", 1515);。
3、编译器运行test.cpp文件,此时成功通过%x输出了十六进制的格式。
参考技术B 首先 浮点数2.5写成二进制应该为10.1(其中整数部分10b=2d, 小数部分0.1*2=1所以0.1b为0.5d)。然后要把10.1规格化(写成1.xxxx * 2^n的形式,有点像科学计数法)得到1.01*2^1(其中2^1中的1为阶码, 1.01为有效数字)
加上2.5为正数,这就得到三部分信息:
1. 有效数字为1.01.
2. 阶码为1.
3. 符点数为正数
而c/c++的float类型结构为:
1. 最低的23位记录规格化小数中的有效数字(但是不保存最前面的1)
2. 之后的8位记录阶码(上面的阶码转换到这里要+127)
3. 最高的一位表示正负数(0为正数,1为负数)
最终得到的二进制数为:
高位 低位
0 10000000 01000000000000000000000
整理得:
0100 0000 0010 0000 0000 0000 0000 0000
转到16进制得:
40200000
注意:0 无穷大 在符点数里比较特殊另外处理(我也不太明白-_-!)追问
那里具体怎么得到那么长的二进制数的我还是没有看懂,8位记录阶码没明白。。。
那里具体怎么得到那么长的二进制数的我还是没有看懂,8位记录阶码没明白。。。
追答有效数字得到 1.01应该没有问题吧
那么1.01 = 1.010 = 1.0100 ... 小数部分后面可以加无数的0, 跟整数部分在前面加无数的0是一个道理。
如果是10进制的话 12345 = 1.2345 * 10^4 那么4就阶码, 1.2345是有效数字。
同理,2进制的 10.1 = 1.01 * 2^1 1为阶码 1.01为有效数字(更为特殊是整数部分只能为1, 因为为0的话,就不是有效数字了)
float Hex_To_Decimal(unsigned char *Byte,int num)//十六进制到浮点数
// char cByte[4];//方法一
// for (int i=0;i<num;i++)
//
// cByte[i] = Byte[i];
//
//
// float pfValue=*(float*)&cByte;
//return pfValue;
return *((float*)Byte);//方法二
long FloatTohex(float HEX)//浮点数到十六进制转换1
return *( long *)&HEX;
void FloatToByte(float floatNum,unsigned char* byteArry)////浮点数到十六进制转换2
char* pchar=(char*)&floatNum;
for(int i=0;i<sizeof(float);i++)
*byteArry=*pchar;
pchar++;
byteArry++;
void main()
unsigned char floatToHex[4];
unsigned char hexbyte[4]=0xcd,0xCC,0xCC,0x3D;//传输数据为3d cc cc cd
float Hdecimal=0.0;
float flh=0.4;
// int num=sizeof(hexbyte);
// printf("num= %d\n",num);
Hdecimal=Hex_To_Decimal(hexbyte,sizeof(hexbyte));//十六进制转换为浮点数
printf("\n 浮点数为:\n %f\n",Hdecimal); 参考技术D
那是件比看起来复杂的事哦。要是真好奇,你看看这个文章。。。
c 浮点数
一、二进制小数
十进制小数: 12.3410 == 1 * 101 + 2 * 100 + 3 * 10-1 + 4 * 10-2 = 12(34/100)
(可能很多人还不知道怎么计算一个数的负幂,这里给大家一个方法:一个数的负的X次方等于这个数的X次方分之一,比如2-2 = 0.25 = 1/2*2 = 1/4,现在明白不?)
二进制小数:101.11 == 1 * 22 + 0 * 21 + 1 * 20 + 1 * 2-1 + 1 * 2-2 = 4 + 0 + 1 + 1/2 + 1/4 = 5(3/4)
从二进制小数可以看出点左边的位的权是2的正幂;而点右边的位是2的负幂
下图是数b的定义:
从该图中不难看出有两种情况:
a>. 把小数点向左移动一位的时候相当于这个数被除以2(比如:101.112 = 5.75 --- 往左移动一位 -->10.1112 = 1 * 22 + 0 * 21 + 1 * 2-1 + 1 * 2-2 +1 * 2-3 = 2 + 0 + 1/2 + 1/4 + 1/8 = 2(7/8) = 2.875,)
b>. 把小数点向右移动一位的时候相当于这个数被乘于2(比如:101.112 = 5.75 --- 往左移动一位 -->1011.12 = 1 * 23 + 0 * 22 + 1 * 21 + 1 * 20 +1 * 2-1 = 8 + 0 + 2 + 1 + 1/2 = 11(1/2) = 11.5)
注意:
a>. 比如0.1,11112这样的数,刚好小于1,这样的数表示(63/64),我们使用科学计数法来表示:1.0-€
b>. 比如1/3、5/7这样的数,就是二进制小数所表单不了的,二进制小数表示法只能表示那些能够被写成x * 2y 的数
下面是一些题目,咱们借着题目分析一下(这个题目是深入理解计算机系统第三版的练习题):
疑问:
1.如何知道二进制小数部分有几位小数? 答:看分母,将分母换算成二进制,得到n位二进制数再减1(8 = 1000 = 4-1 = 3),比如1/8 = 0.001、1/2 = 0.1、1/16 = 0.0001
2.分子换算成小数部分后从小数点往右 位权越大还是越小? 答:从小数点往右二进制位的权越来越小,比如:1/16 =0.0001(有人计算出来是0.1000,这样是错的,这样的结果就是8/16 = 1/2 = 0.5 = 5 * 10-1 = 5/10 = )-------->这里涉及到十进制小数转二进制小数的问题,就是用小数去乘以2,不断的取整数:0.5 * 2 = 1.0 取1,小数部分就是1,结果就是0.1,一直乘以2,知道结果为1.0位置
a>. 3/8,首先分子比分母小,结果小于1;分母为8抓成二进制1000,小数部分则是n-1 = 3,分子部分011(是从右往左的),结果就是0.011;十进制:0.(1 * 2^-2 + 1 * 2^-3) = 3/8 = 0.375
b>. 23/16,首先分子大于分母,结果大于1,先计算整数部分为1,剩余为7/16,确定几位小数16 = 10000,小数位n-1 = 4,分子转成4位二进制 = 0111,结果就是1.0111;十进制:1 * 2^0 + 1 * 2^-2 + 1 * 2^-3 + 1 * 2^-4 = 1 + 0.25 + 0.125 + 0.0625 = 1.4375
c>. 10.1101,逆向运算 1 * 2^1 + 1 * 2^-1 + 1 * 2^-2 + 1 * 2^-4 = 2 + 1/2 + 1/4 + 1/16 = 2 + 13/16 = 45/16;十进制:2.8125
d>. 1.011 === 1 * 2^1 + 1 * 2^-2 + 1 * 2^-3 = 1 + 4/8 + 1/8 = 13/8 = 1.625
e>. 5.375 首先整数部分是5 = 101,小数部分是0.375,按照十进制小数转二进制小数,不断乘2,取整数(011),小数部分是011,结果就是101.011;小数值:5(3/8) = 43/8
f>.3.0625 首先整数部分是3 = 11,小数部分0.0625 = 0001,结果就是11.0001;小数值:3(1/16) = 49/16
二、IEEE浮点表示
IEEE浮点标准(表示一个数):V = (-1)s * M * 2E (不太理解)
介绍:
符号(s):决定数是负数(s == 1)还是整数(s == 0),而对于数值0的符号位解释作为特殊情况处理
有效数(M):它是一个二进制小数,它的范围在1~2-€或者0~1-€之间
指数(E):2的幂(正负都有可能),它的作用是对浮点数加权
浮点数的位分为三个域,编码值:
符号位(s):决定正负
尾数(M):一个二进制小数
阶码(E):对浮点数加权
存储一个浮点数(s正负号、exp指数E,frac小数部分):
对于单精度浮点格式(32位):
对于双精度浮点格式(64位):
根据阶码(E)字段的值不同我们可以分为四类浮点数:
a>. 规格化浮点数:
规格化浮点数:阶码值E = e - bias(2k-1 -1),bias在单精度情况下是127,双精度情况下是1023,因此单精度下E的值为[-126~+127],在双精度下E的值为[-1022~+1023];对于小数字段frac,f =0. fn-1fn-2.....f0,而位数M = f +1;在这里我们将浮点数的首位默认为1,所以没有显示的存储在存储器中,为什么能这样呢?因为我们可以通过调整阶码值E,使小数部分二进制的值落在1~2之间,获得额外的精度为
例如:0.10111,存储的话小数部分的二进制位是5位,存储就是000...10111,但是浮点数首位默认为1之后,我们小数部分存4位就可以了,1.0111 * 2-1 (why??前面咱们提到过,二进制小数,小数点往左移动一位就是除以2,往右移动就是乘以2,在这里我们往右移动了一位,结果就是1.0111,那么我们还原回去保持值不变就必须除以2,也就是*1/2)
表示范围:单精度下[-2^127,2^127],双精度下[-2^1023,2^1023],那么规范化的绝对值是大于 2 ^ (-126) 或 2 ^ (-1022) 的数字
示例1:0.25,先转成二进制小数0.01,那么根据规范化的属性转换一种形式,小数点往右移动2位 (0.01 * 2^2) * 2^-2 = 1.0 * 2^-2,根据阶码值计算E = -2 + 127 = 125,二进制小数部分全部都是0,那么最后的结果就是0 0111 1101 0000 0000 0000 0000 0000 000
示例2:1.5,转成二进制1.1,规格化默认首位为1,先忽略,0.1 * 2^0,那么阶码E = 127 + 0 = 127 = 01111111,小数部分1,后边补齐0即可,结果就是0 0111 1111 1000 0000 0000 0000 0000 000
b>. 非规格化浮点数:
非规格化浮点数:定义阶码E = 1 - bias (2k-1 -1),M = f = 0.fn-1 fn-2 fn-3 …… f2 f1 f0
表示范围:非规范化浮点数表示的则是小于 2 ^ (-126) 或 2 ^ (-1022) 的值
c>. 无穷大:
无穷大:frac部分二进制小数全为0
d>. NaN(Not a Number)
NaN:frac部分二进制小数不全为0
下边是几个文章的链接(写的特别好):
http://blog.csdn.net/hqin6/article/details/6701109
http://www.atjiang.com/CSAPP3-2.4_floating_point/
https://yasicyu.com/newarticle/IEEE-754%E6%A0%87%E5%87%86%E4%B8%8E%E5%AE%9E%E7%8E%B0
下面是一些练习题,本人对这一部分不是很懂,所以记录一下面试题的分析过程:
IEEE浮点格式的5位浮点数表示,1位符号位、2个指数位(k=2)和2位小数,指数偏移量bias = 2k-1 - 1 = 1
注意(0 00 00):
1.IEEE754浮点数表达式: V = M * 2e bias = 2k-1 - 1 = 1
2. 规格化数:E = e - Bias = e - 2k-1 - 1;M = f + 1
2.1 规格化数的范围:小数部分 0+1 = 1 ~ 1+3/4 = 7/4, V的范围 1 * 2^-1 = 1/2 ~ 2 * 7/4 = 14/4
3.非规格化数:E = 1 - Bias = 1 - 2k-1 - 1;f = M
3.1.非规格化数的范围:小数部分 0 ~ 3/4;阶码值为0,V的范围0 ~ 3/4
开始做题:
a>. 0 00 00: e = 0; E = 1-bias = 0; f = 0; M = 0; V = 0;
b>. 0 00 01: e = 0; E = 0; f = 1/4; M = f = 1/4; V = 1/4 * 2^0 = 1/4
c>. 0 00 10: e = 0; E = 0; f = 2/4; M = f = 2/4; V = 2/4 * 2^0 = 2/4
d>. 0 00 11; e = 0; E = 0; f = 3/4; M = f = 3/4; V = 3/4 * 2^0 = 3/4
e>. 0 01 00(这个就不再是非规格化数了,非规格化数的特点是阶码值全为0,这个符合规格化数):e = 1; E = e - Bias = 1 - 1 = 0; f = 0; M = f + 1 = 4/4; V = 2^0 * 4/4 = 4/4
f>. 0 01 01: e = 1; E = 0; f = 1/4; M = f + 1 = 5/4; V = 2^0 * 5/4 = 5/4
g>. 0 01 10: e = 1; E = 0; f = 2/4; M = f + 1 = 6/4; V = 2^0 * 6/4 = 6/4
h>. 0 01 11: e = 1; E = 0; f = 3/4; M = f + 1 = 7/4; V = 2^0 * 7/4 = 7/4
i>. 0 10 00: e = 2; E = 1; f = 0; M = f + 1 = 4/4; V = 2^1 * 4/4 = 8/4
j>. 0 10 01: e = 2; E = 1; f = 1/4; M = f +1 = 5/4; V = 2^1 * 5/4 = 10/4
k>. 0 10 10: e = 2; E = 1; f = 2/4; M = f +1 = 6/4; V = 2^1 * 6/4 = 12/4
l>. 0 10 11: e = 2; E = 1; f = 3/4; M = f + 1 = 7/4; V = 2^1 * 7/4 = 14/4
m>. 0 11 00 :这种情况就是无穷大的情况,因为阶码值全是1,小数部分全是0
n>. 0 11 01: 这种情况就是NaN了,因为阶码值全是1,而小数部分不全是0(e = 3; E = 2; f = 1/4; M = f + 1 = 5/4; V = 2^2 * 5/4 = 20/4 > 14/4)
三、浮点数舍入
浮点数舍入有四种方法,默认的舍入方法:向偶数舍入(round-to-even),也被称为向最接近的值舍入;其他三种方法产生的实际值的确界;
向偶数舍入:它试图找到最接近的值,采用的方法是将数字向上或者向下舍入,使得结果的最低有效位是偶数
比如:1.5RMB、2.5RMB想偶数舍入的结果都是2RMB
向零舍入:正数向下舍入,负数向上舍入,|x^| <= |x|
向下舍入:把正数和负数都向下舍入,x- < x
向上舍入:吧正数和负数都向上舍入,x+ > x
四、浮点数运算
浮点数不具有结合性
对于任何x,都有NaN + x = NaN
浮点数满足单调性熟属性:a>=b ,对于任何a,b的值,除了x不等于NaN,都有x + a >= x + b
五、浮点数
int、float、double三个类型相互转换:
a>. int转float,数值不会溢出,可能会被舍去
b>. int、float转double,因为double的范围更大,也有更高的位数(更多的有效位),能够保留精确的值
c>.double转float,从大范围转成小范围,所以值可能会溢出成+∞或-∞,由于精度较小,可能会被舍去
d>. double、float转int值将会向0截断,比如1.9999将会等于1,-1.99999将会等于-1
以上是关于c语言、浮点数怎么变成16进制的主要内容,如果未能解决你的问题,请参考以下文章