C 将浮点数(IEEE-754)打包到uint64\u t的代码的规范化部分

C 将浮点数(IEEE-754)打包到uint64\u t的代码的规范化部分,c,floating-point,ieee-754,C,Floating Point,Ieee 754,我一直在研究一种便携式方法,以二进制格式(在uint64_t中)存储浮点,以便通过网络将其共享给各种微控制器。它应该独立于系统的浮点内存布局和端性 我遇到了这个。但是,我无法理解代码中的几行,如下所示: while(fnorm >= 2.0) { fnorm /= 2.0; shift++; } while(fnorm < 1.0) { fnorm *= 2.0; shift--; } fnorm = fnorm - 1.0; // calculate the binary for

我一直在研究一种便携式方法,以二进制格式(在uint64_t中)存储
浮点
,以便通过网络将其共享给各种微控制器。它应该独立于系统的浮点
内存布局
端性

我遇到了这个。但是,我无法理解代码中的几行,如下所示:

while(fnorm >= 2.0) { fnorm /= 2.0; shift++; }
while(fnorm < 1.0) { fnorm *= 2.0; shift--; }
fnorm = fnorm - 1.0;

// calculate the binary form (non-float) of the significand data
significand = fnorm * ((1LL<<significandbits) + 0.5f);
while(fnorm>=2.0){fnorm/=2.0;shift++;}
而(fnorm<1.0){fnorm*=2.0;移位--;}
fnorm=fnorm-1.0;
//计算有效位数据的二进制形式(非浮点)

有效位=fnorm*((1LLwhile
循环调整指数,以便将
fnorm
的第一个二进制1放置在点(以基数2为单位)之前。
因此,在基数2中,fnorm最多为1.1111111…在基数10中几乎为2.0。
至少
fnorm
在基数2中为1.000000…在基数10中为1.0。

在IEEE754中,标准化数字(非次标准)的有效位的形式为1.xxxxxx…(基数2),这与前面的循环一致。
点之前的第一位总是1,这就是为什么不必记住它的原因 (也许这最后一句话是你问题的重点)

归一化后,您的算法减去1.0,这将导致0.xxxxx…正如您所看到的。
减法1.0不会丢失任何信息,只要我们记住这个减法是系统的。

乘以此浮点值(严格小于1.0,但不为负值)整数
1lot:我的偏好是使用无处不在的文本格式,而不是发明另一种格式,这需要用户进行全面的文档记录和理解。一个
float
可以以文本形式存储在大约10个字节中,也可以被人读取。我需要通过一个可以接受消息中20个字节的流进行通信。我不能使用文本格式。在任何情况下,前两行用于调整数字的比例,使其处于半开区间[1,2)。一旦知道它在该间隔内,乘以2**
有效位并转换为整数将生成有效位的副本。在该乘法之前减去1将删除正常数字有效位中隐含的前导1位。该代码不适合处理次正常数字。此外,循环是不必要的;C提供了提取分数(有效位)的
frexp
函数和浮点数的指数。IEEE-754已完全指定为位级别。只需为传输选择一个端号,并确保每个端在需要时进行转换。因此,编写代码以将任何符合C的浮点类型转换为单一格式(如IEEE-754 binary32)因为传输涉及大量代码,它需要执行从一个基到另一个基的转换,可能是非常大或非常小的数字,需要数千位数字。您真的不希望这样。最有可能的是,您想要的解决方案使用预处理器测试
中定义的值,以确保IEEE-754格式正在使用,然后继续发送
浮点
双精度
的字节,无需任何转换,只需调整字节顺序。有效位并不总是具有“1.xxxxxx…”形式它的前导1表示正常数,前导0表示次正常数。序列化和反序列化浮点数据的代码必须考虑到这一点。(“有效位”是浮点表示的小数部分的首选术语。“尾数”是对数小数部分的旧术语。)@EricPostphil是的,谢谢,因为我不知道这背后的确切动机,可能是我应该删除…我担心这个答案比有用的答案更令人困惑。取决于问题的真正意义;我猜是关于-1.0的,但是,在这种情况下,我不确定答案是否有用。只是确保fnorm在0.0之间和1.0(十进制),使其转换为1.xxxxxx形式…二进制?