ninja_ken  

做过网络编程的程序员们,都知道在进行二进制数据传输时,绕不开所谓“大小端”的问题(如果不清楚,请自行百度下哈)。之前以为只有Integer才会做大小端转换,今天发现其实对于多字节的数据,比如单精度/双精度浮点数,其实也有大小端的考虑。下面以单精度浮点数为例说明

根据二进制浮点数算术标准(IEEE754),32位单精度浮点数的二进制表示如下图所示(左端为MSB高位,右端为LSB低位)

所以现在的问题是,

  1. 在计算机内存中,低地址存放的是最右边的fraction(小数位部分),还是最左边的sign(符号)和exponent(指数)部分呢?
  2. 在传输一个单精度浮点数时,我们应该先传输最右边的fraction(小数位部分),还是最左边的sign(符号)和exponent(指数)部分呢?

答案是这些和处理整数的时候一样,要区分大小端。比如在我的Intel处理器(默认小端)的PC上,下面一段程序

#include <iostream>

void PrintBytes(float n) {
    auto ch = reinterpret_cast<uint8_t*>(&n);
    // 从低地址开始打印,每次一个字节
    for (int i = 0; i < sizeof(n); ++i) {
        std::cout << std::showbase << std::hex << static_cast<int>(*(ch + i)) << std::endl;
    }
}

int main() {
    PrintBytes(2.0);
    return 0;
}

运行后打印的结果是

对于单精度浮点数2.0,按照IEEE标准,32比特的二进制形式如下(这里的指数部分100000000等于十进制的128,表示数值1,因为指数部分为了表示正、负幂,用127表示数值0,更多详情请参考其他资料)

符号(MSB) 指数 小数(LSB)
0 10000000 00000000000000000000000

所以可以看到,先打印的是低比特位(LSB)的小数部分,后打印的符号+指数高比特位(MSB)部分,也就是说Intel处理器在低地址存放浮点数的低位,高地址存放浮点数的高位。等等,小端的定义——在低地址存放低bit位,高地址存放高比特位——不正是这个吗?正是如此。所以结论就是,在Intel处理器中浮点数也是按照小端存储的。在网络传输浮点数时,也需要考虑大小端。

posted on 2022-06-22 10:29  ninja_ken  阅读(1493)  评论(0编辑  收藏  举报