IEEE754 浮点数计算器 C语言版

1. 问题和别人的工作

IEEE754是浮点数在计算机中存储的技术规范。在学习手动计算 科学计数法/小数形式 与 二进制/十六进制 相互转换的过程中,我们可以使用IEEE754浮点数计算器帮助检验计算结果。

网上不少有在线的IEEE754浮点数计算器,都能符合要求1.你给出小数形式,计算器算出二进制;2.你给出二进制,计算机器算出小数形式。

比如

https://www.h-schmidt.net/FloatConverter/IEEE754.html

界面长这样。

再如

http://www.binary-calculator.com/

界面长这样。

如果没有网怎么办?这里给出一个C语言版的。

2. hex2float,我给出二进制,计算器求浮点数

偷了两个懒。第一,既然二进制和十六进制转换非常简单,是程序员的基本功,因此就不实现了。我给出的不是二进制格式,而是十六进制,如0x12345678。以下,不对二进制和十六进制作区分。第二,不从控制台或者命令行参数,而是硬编码,在代码中给变量赋值。这两点都不是技术难点。

代码如下。

#include <cstdio>

#include <cstdlib>

int main()

{

float f = 1;

*(unsigned int*)&f = 0x12345678;

printf("%x\n",*(unsigned int*)&f);

printf("%e\n",f);

return(0);

}

运行的结果是这样的:

>hex2float.exe

0x12345678

5.690457e-28

即,你手动把二进制0x12345678转换成浮点数,如果结果是5.690457e-28,那么就做对了。

涉及到的核心技巧,*(unsigned int*)&f = 0x12345678; 是把 float 型变量f 取地址得到指针,再转换指针基类型为(unsigned int*),最后去地址引用再赋值。

交叉检验一下。

二进制0x12345678对应的IEEE754浮点数在
https://www.h-schmidt.net/FloatConverter/IEEE754.html
可以得到,如下图所示。是5.690457e-28附近没错。

如果需要计算别的二进制,把代码中的0x12345678改成想求的数就行了。

3. float2hex,我给出浮点数,计算器求二进制

代码如下。

#include <cstdio>

#include <cstdlib>

int main()

{

float f = 5.6904566139e-28; //0x12345678

int a = *(unsigned int*)&f;

//a = 0x12345678;

printf("%x %x %x %x\n",a%0x100, a/0x100%0x100, a/0x10000%0x100, a/0x1000000);

FILE *fp;

fp = fopen( "file.bin" , "w" );

fwrite(&f, sizeof(char) , 4, fp );

fclose(fp);

return(0);

}

核心技巧是 int a = *(unsigned int*)&f; 这一行,把等号右边的(float型变量通过指针得到的)整型变量的值取出来。下一行,是标准的计算机等级考试二级题目思路,通过取整和求余操作,得到整数切成十六进制每2位一段。

运行结果如下。

>float2hex

78 56 34 12

为什么这么“颠倒”排列显示呢?明明代码里是先低权重后高权重的。我们可以把这4个字节作为4个char写到磁盘文件中对比一下。

用十六进制工具查看file.bin的内容,如下。

也是颠倒存放的。输出到控制台的写法,是为了与内存中的存放次序,也即磁盘文件的存放次序保持一致。之所以在内存中顺序如此,是因为我的计算机是Intel系列CPU,小端模式。为什么向控制台输出看起来像大端,所以还需要特意颠倒输出顺序呢?因为那是整数,不是内存映射,低字节 vs. 高字节,而是 低权重 vs. 高权重,且与地址无关。

IEEE754并不遥远,一点也不陌生,就在常见的C语言的代码之中,一直就在我们身边,只是我们不一定看得到。

Leave a Reply

Your email address will not be published. Required fields are marked *