c语言 单精度浮点数是怎样转换成2进制数

供稿:hz-xin.com     日期:2025-01-14
c语言如何把浮点数转换成二进制

这就设计到浮点数的 表示方法了:

C语言和C#语言中,对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用32bit,double数据占用64bit,我们在声明一个变量float f= 2.25f的时候,是如何分配内存的呢?如果胡乱分配,那世界岂不是乱套了么,其实不论是float还是double在存储方式上都是遵从IEEE的规范的,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53。

无论是单精度还是双精度在存储中都分为三个部分:

符号位(Sign) : 0代表正,1代表为负

指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储

尾数部分(Mantissa):尾数部分
其中float的存储方式如下图所示:


而双精度的存储方式为:



R32.24和R64.53的存储方式都是用科学计数法来存储数据的,比如8.25用十进制的科学计数法表示就为:8.25*,而120.5可以表示为:1.205*,这些小学的知识就不用多说了吧。而我们傻蛋计算机根本不认识十进制的数据,他只认识0,1,所以在计算机存储中,首先要将上面的数更改为二进制的科学计数法表示,8.25用二进制表示可表示为1000.01,我靠,不会连这都不会转换吧?那我估计要没辙了。120.5用二进制表示为:1110110.1用二进制的科学计数法表示1000.01可以表示为1.0001*,1110110.1可以表示为1.1101101*,任何一个数都的科学计数法表示都为1.xxx*,尾数部分就可以表示为xxxx,第一位都是1嘛,干嘛还要表示呀?可以将小数点前面的1省略,所以23bit的尾数部分,可以表示的精度却变成了24bit,道理就是在这里,那24bit能精确到小数点后几位呢,我们知道9的二进制表示为1001,所以4bit能精确十进制中的1位小数点,24bit就能使float能精确到小数点后6位,而对于指数部分,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127-128了,所以指数部分的存储采用移位存储,存储的数据为元数据+127。

下面就看看8.25和120.5在内存中真正的存储方式。
首先看下8.25,用二进制的科学计数法表示为:1.0001*
按照上面的存储方式,符号位为:0,表示为正,指数位为:3+127=130 ,位数部分为,故8.25的存储方式如下图所示:


而单精度浮点数120.5的存储方式如下图所示:


那么如果给出内存中一段数据,并且告诉你是单精度存储的话,你如何知道该数据的十进制数值呢?其实就是对上面的反推过程,比如给出如下内存数据:0100001011101101000000000000,首先我们现将该数据分段,0 10000 0101 110 1101 0000 0000 0000 0000,在内存中的存储就为下图所示:


根据我们的计算方式,可以计算出,这样一组数据表示为:1.1101101*=120.5
而双精度浮点数的存储和单精度的存储大同小异,不同的是指数部分和尾数部分的位数。所以这里不再详细的介绍双精度的存储方式了,只将120.5的最后存储方式图给出,大家可以仔细想想为何是这样子的


下面我就这个基础知识点来解决一个我们的一个疑惑,请看下面一段程序,注意观察输出结果
float f = 2.2f; double d = (double)f; Console.WriteLine(d.ToString("0.0000000000000")); f = 2.25f; d = (double)f; Console.WriteLine(d.ToString("0.0000000000000"));

可能输出的结果让大家疑惑不解,单精度的2.2转换为双精度后,精确到小数点后13位后变为了2.2000000476837,而单精度的2.25转换为双精度后,变为了2.2500000000000,为何2.2在转换后的数值更改了而2.25却没有更改呢?很奇怪吧?其实通过上面关于两种存储结果的介绍,我们已经大概能找到答案。首先我们看看2.25的单精度存储方式,很简单 0 1000 0001 001 0000 0000 0000 0000 0000,而2.25的双精度表示为:0 100 0000 0001 0010 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000,这样2.25在进行强制转换的时候,数值是不会变的,而我们再看看2.2呢,2.2用科学计数法表示应该为:将十进制的小数转换为二进制的小数的方法为将小数*2,取整数部分,所以0.282=0.4,所以二进制小数第一位为0.4的整数部分0,0.4×2=0.8,第二位为0,0.8*2=1.6,第三位为1,0.6×2 = 1.2,第四位为1,0.2*2=0.4,第五位为0,这样永远也不可能乘到=1.0,得到的二进制是一个无限循环的排列 00110011001100110011... ,对于单精度数据来说,尾数只能表示24bit的精度,所以2.2的float存储为:


但是这样存储方式,换算成十进制的值,却不会是2.2的,应为十进制在转换为二进制的时候可能会不准确,如2.2,而double类型的数据也存在同样的问题,所以在浮点数表示中会产生些许的误差,在单精度转换为双精度的时候,也会存在误差的问题,对于能够用二进制表示的十进制数据,如2.25,这个误差就会不存在,所以会出现上面比较奇怪的输出结果

了解了浮点数的存储方式后,转成二进制应该就简单很多了,希望这点东西对你有用,望采纳!

整数部分用16除,反向取余数;小数部分用16乘,正向取整数。具体如下:
22÷16 = 1 余 6
1÷16 = 0 余 1
所以整数部分是16。小数部分
0.84x16 = 13(D) . 44
0.44x16 = 7 .04
0.04x16 = 0 .64
0.64x16 = 10(A) .24
0.24x16 = 3 .84
0.84x16 = 13(D) . 44
...以后循环了,所以
22.84(10) = 16.D70A3D70A3...(16)
还可以先“用2除反向取余数”和“用2乘正向取整数”变成二进制,再从小数点开始左右每4位分开,前后不足4位的用0补齐,然后用对应的16进制符号直接写出来就可以了。22.84化成二进制是10110.11010111000010100011...→1'0110.1101'0111'0000'1010'0011→0001'0110.1101'0111'0000'1010'0011→16.D70A3...
要写代码,如下便可:
#include "stdio.h"int main(void){ double x=22.84,t; char h[17]="0123456789ABCDEF", i,k; printf("%g(10) = %x.",x,int(x)); for(t=x-int(x),i=0;i<10;i++){ k=int(t*=16),t-=k; printf("%c",h[k]); } printf("...(16)
"); return 0;} C/C++没有提供以指针形式输出16进制数据的功能。

在C++里,实数(float)是用四个字节即三十二位二进制位来存储的。其中有1位符号位,8位指数位和23位有效数字位。实际上有效数字位是24位,因为第一位有效数字总是“1”,不必存储。 有效数字位是一个二进制纯小数。8位指数位中第一位是符号位,这符号位和一般的符号位不同,它用“1”代表正,用”0“代表负。整个实数的符号位用“1”代表负,“0”代表正。
在这存储实数的四个字节中,将最高地址字节的最高位编号为31,最低地址字节的最低位编号为0,则实数各个部分在这32个二进制位中的分布是这样的:31位是实数符号位,30位是指数符号位,29---23是指数位,22---0位是有效数字位。注意第一位有效数字是不出现在内存中的,它总是“1”。

将一个实数转化为C++实数存储格式的步骤为:
(1)先将这个实数的绝对值化为二进制格式,注意实数的整数部分和小数部分化为二进制的方法是不同的。
(2)将这个二进制格式实数的小数点左移或右移n位,直到小数点移动到第一个有效数字的右边。
(3)从小数点右边第一位开始数出二十三位数字放入第22到第0位。
(4)如果实数是正的,则在第31位放入“0”,否则放入“1”。
(5)如果n 是左移得到的,说明指数是正的,第30位放入“1”。如果n是右移得到的或n=0,则第30位放入“0”。
(6)如果n是左移得到的,则将n减去一然后化为二进制,并在左边加“0”补足七位,放入第29到第23位。如果n是右移得到的或n=0,则将n化为二进制后在左边加“0”补足七位,再各位求反,再放入第29到第23位。

将一个计算机里存储的实数格式转化为通常的十进制的格式的方法如下:
(1)将第22位到第0位的二进制数写出来,在最左边补一位“1”,得到二十四位有效数字。将小数点点在最左边那个“1”的右边。
(2)取出第29到第23位所表示的值n。当30位是“0”时将n各位求反。当30位是“1”时将n增1。
(3)将小数点左移n位(当30位是“0”时)或右移n位(当30位是“1”时),得到一个二进制表示的实数。
(4)将这个二进制实数化为十进制,并根据第31位是“0”还是“1”加上正号或负号即可。

特别地,实数0用C++的float格式表示是00000000000000000000000000000000。

如果还不太明白,这里举几个例子。
一。将23.56化为C++的float格式。
(1)将23.56化为二进制后大约是“10111.1000111101011100001”。

**** 首先将一个小数如:235.725的小数部分取出,即:0.725,将其乘以进制数二进制就乘以2后得到1。45,取其整数部分1为二进制小数的第一项(十分位),在将小数部分0。45乘2得0。9,取其整数部分为二进制小数的第二位(百分位)0,在将其小数部分0。9乘2,得1。8,取其整数部分为二进制小数的第三位(千分位)1,取其小数部分0。8再乘2……以此类推,直到值为0或形成循环小数则停止。

(2)将小数点左移四位,得到“1.01111000111101011100001”。
(3)这已经有了二十四位有效数字,将最左边一位“1”去掉,得到“01111000111101011100001”。将它放入第22到第0位。
(4)因为23.56是正数,因此在第31位放入“0”。
(5)由于我们把小数点左移,因此在第30位放入“1”。
(6)因为我们是把小数点左移4位,因此将4减去1得3,化为二进制,并补足七位得到0000011,放入第29到第23位。
完毕。
如果把最左边定为第31位,最右边定为第0位,那么在C++里,float格式的23.56是这样表示的:01000001101111000111101011100001。相应地-23.56就是这样表示的:11000001101111000111101011100001。

二。将实数0.2356化为C++的float格式。
(1)将0.2356化为二进制后大约是0.00111100010100000100100000。
(2)将小数点右移三位得到1.11100010100000100100000。
(3)从小数点右边数出二十三位有效数字,即11100010100000100100000放入第22到第0位。
(4)由于0.2356是正的,所以在第31位放入“0”。
(5)由于我们把小数点右移了,所以在第30位放入“0”。
(6)因为小数点被右移了3位,所以将3化为二进制,在左边补“0”补足七位,得到0000011,各位取反,得到1111100,放入第29到第23位。
完毕。因此0.2356用C++的float格式表示是:00111110011100010100000100100000。其中最左边一位是第31位,最右边一位是第0位。

三。将实数1.0化为C++的float格式。
(1)将1.0化为二进制后是1.00000000000000000000000。
(2)这时不用移动小数点了,这就是我们在转化方法里说的n=0的情况。
(3)将小数点右边的二十三位有效数字00000000000000000000000放入第22到第0位。
(4)因为1.0是正的,所以在第31位里放入“0”。
(5)因为n=0,所以在第30位里放入“0”。
(6)因为n=0,所以将0补足七位得到0000000,各位求反得到1111111,放入第29到第23位。
完毕。所以实数1.0用C++的float格式表示是:00111111100000000000000000000000。其中最左边一位是第31位,最右边一位是第0位。

能不能给我讲讲C语言中实数的二进制形式,是怎样存储的?
无论是单精度还是双精度在存储中都分为三个部分:符号位(Sign):0 代表正,1 代表为负。指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储。尾数部分(Mantissa):尾数部分。下面举例一个浮点数如何存储转换的(以float为例)以浮点数18.75为例 首先转化为二进制即10010.11 转化为...

汇编语言 浮点数表示方法
IEEE754浮点数格式 短实数也称单精度数 符号位1位,阶码8位,尾数23位 42 12 80 00化为2进制 0100 0010 0001 0010 1000 0000 0000 0000 ||<--->| | 这八位是阶码:1000 0100=84H=132,减去127=5表示2^5=32,| 第一位是0,表示正数 剩下是尾数001 0010 1000 0000 0000 0000 .4.6...

单精度浮点数和十进制怎么转换
在数字转换过程中,首先需要对数字进行分割,这包括分离数字的符号、阶码和有效数字。符号用于确定数字的正负,阶码表示数字的大小级别,而有效数字则构成了数字的实际数值部分。接下来,将偏移阶码减去一个固定的偏移值,以得到真正的阶码。这一步骤通常是为了将浮点数表示成标准的二进制形式,便于后续的运算...

c语言里单精度和双精度怎么理解?
单精度和双精度顾名思义是两种精度的不同划分,单精度float是保证7位有效数字,double是保证16位有效数字。例:(float)(10%3)结果是1.000000即七位有效数字,(后面不一定全是0,计算机可随机选择数字,所以整数1不等于float或double的1)(double)(10%3)同理结果是:1.XXXXXXXXXX……后面有...

浮点型数据的相互转换
标准4字节浮点型在计算机里存储方式如下图IEEE754标准中浮点数表示格式IEEE规定的浮点数表示法是一种科学计数法,用符号(正或负)、指数和尾数来表示,底数被确定为2。也就是说浮点数被表示为尾数乘以2的指数次方再带上符号。具体格式如下: 符号域 指数域 小数域 指数偏移量 单精度浮点数 ...

为什么单精度浮点数的十进制精度是7位,我按照23位尾数的理解精度应该...
在计算机中,浮点数的精度主要由尾数的位数决定。对于单精度浮点数,其尾数部分有23位。将23个尾数转换为十进制后,可以表示大约7位有效数字,因此,单精度浮点数的精度为7位。反过来,我们再看数字1.12345678,这是一个具有8位十进制有效数字的数字。将其转换为二进制表示时,需要30个尾数位才能精确...

如何计算单精度浮点数-9.625的二进制数值。
二进制小数0.11转换十进制为1\/2+1\/4=0.75。0.11二进制转换为16进制,先把小数部分补成四位,即0.1100。根据转换关系,首先1100为十进制的12,转换16进制为C。所以0.11B转换16进制就是0.CH(H表示其是16进制数)单精度浮点数,-9.625,首先需要转换为二进制数,容易得-9.625= (-1001....

单精度浮点数和十进制怎么转换
一、单精度浮点数符合IEEE754标准,32位,前面第一位是符号位,接下来的8位是指数,最后23位是尾数。编程中了解这些就够了,转换方法如下:二、VB中转换示例:VB浮点数转换程序 OptionExplicit'利用函数CopyMemory转换 PrivateDeclareSubCopyMemoryLib"kernel32"Alias"RtlMoveMemory"(DestinationAsAny,...

单精度和双精度有什么不同?
4,精度不同。 float在表示十进制时,有效数字为6到7位。double在表示十进制时,有效数字为15到16位。,5.输入输出格式不同。在C语言中,输入输出格式化字符串,float使用%f,而double使用%lf。6,单精度和双精度都属浮点数,一个单精度浮点数占4个字节(32位),一个双精度浮点数占8个字节(64位...

十进制数232的IEEE754单精度浮点数代码是什么?
符号位 + 指数位 + 尾数位 其中,符号位占用1位,指数位占用8位,尾数位占用23位。因此,232的IEEE754单精度浮点数代码为:```0 10000111 11010000000000000000000 ```需要注意的是,由于指数位和尾数位都以二进制补码的形式进行存储,因此需要将它们转换为二进制补码再进行拼接。