C中浮点数据类型的结构(二进制格式)是啥?

Posted

技术标签:

【中文标题】C中浮点数据类型的结构(二进制格式)是啥?【英文标题】:What is the struct (binary format) of float datatype in C?C中浮点数据类型的结构(二进制格式)是什么? 【发布时间】:2020-06-01 13:21:38 【问题描述】:

如何在 C 中找到有关 float 数据类型的信息?我的意思是这种类型的位结构(十进制,信号指示符等......)? 让我解释一下我要做什么:

我正在实现一个网络协议,我需要发送 6 个带有纬度和经度的八位字节(根据协议文档)。前 3 个八位字节必须有 LAT 信息,后 3 个必须有 LON 信息。 我不能在float 数据类型中使用按位运算符,所以为了调试,我将float 变量的内存复制到一个新的uint32_t 变量(均为4 字节宽),然后尝试移动位以获得正确的值,但它不起作用。

这是我用来测试/调试转换的代码:

    int32_t b = 0;    
    memcpy(&b,&a,4);
    int32_t c = (b >> 23);        
    printf("Valor de C: 0x%X, Decimal: %d\n",c,c);
// Should print only '23', but it's printing 
// Valor de C: 0x41B, Decimal: 1051

在“知道”float 的正确位位置后,我会将这些位复制到我的协议数据中,该数据是一个 unsigned char[6] 数组(我无法更改类型,只能更改值)。

关于如何做到这一点的任何提示?

【问题讨论】:

你好。根据您粘贴的协议文档,数据不是存储为浮点数而是定点数。您可以在此处阅读有关定点数的信息:en.wikipedia.org/wiki/Q_(number_format)#Conversion。 您不需要为此使用float 类型的内部表示。你只需要价值。您使用的协议显然需要将角度(纬度或经度)编码为整数单位的二进制,其中单位为 180/2**23 度。因此,如果您在 float 中将角度表示为度数,请将其乘以 2**23/180 转换为多个单位,并将结果表示为二进制整数。 ***.com/questions/385132 【参考方案1】:

这是一个示例代码,展示了如何对浮点纬度进行编码。 (经度也是一样)。 请参阅:https://en.wikipedia.org/wiki/Q_(number_format)#Float_to_Q,了解使用 2 个补码管理的定点编码。

它使用规范提供的权重的定点编码。

#include <stdio.h>
#include <stdlib.h>
int main()


    /* weight of one bit */
    const float weight = 180./(1 << 23);
    printf ("w=%f\n",weight);

    /* a few sample conversions */
    /* 2.53 degres */
    float lat = 2.53; 
    printf ("lat=%f\n",lat);

    int fp_lat = (int) (0.5f + lat / weight);
    printf ("fplat=0x%x\n",fp_lat);

    lat = 180.f; /* +180 degres */
    printf ("lat=%f\n",lat);

    fp_lat = (int) (0.5f+ lat / weight);
    printf ("fplat=0x%6x\n",fp_lat); /*exactly 23 bits */

    /* negative numbers)*/
    lat = -180.f; /* -180 degres */

    printf ("lat=%f\n",lat);

    fp_lat = (int) (0.5f + abs(lat) / weight);
    if (lat <0)
    
        /*2 complement representation */
        fp_lat = (~fp_lat + 1) & 0xffffff;
    
    printf ("fplat=0x%6x\n",fp_lat); /* same value as 180 */


    /*sample packing for latitude */
    unsigned char msg[6];
    msg[0] = (unsigned char)((fp_lat >> 16) & 0xff); /* most significant byte of 24 bits*/
    msg[1] = (unsigned char)((fp_lat >> 8 ) & 0xff);
    msg[2] = (unsigned char)((fp_lat      ) & 0xff);

    /* to be continued */
    return 0;


【讨论】:

【参考方案2】:

数据的解释与数据是分开的。数据的单元与数据本身是分开的。所以我可以说123 milliseconds0.123 seconds234 half-milliseconds1.23 * 10^-2 seconds 所有这些形式表示相同的“”。

你发布的数据我猜是由两个数字组成,编码为二进制补码,以大端表示,最高有效位在前。

unsigned char data[6]; // assuming indexes reference octet numbers
// big endian - first byte is the most significant
// I assume the hardware uses twos complement internally 
// the method as described in https://***.com/questions/35876000/converting-24-bit-integer-2s-complement-to-32-bit-integer-in-c
int32_t latitude_value = (int32_t)( data[0] << 24 | data[1] << 16 | data[2] << 8 ) / 256;
// latitude_value represents latitude in units of 180/2^23 degrees

现在,如果您想以这种方式表示它,您可以将 latitute 从 180/2^23 degrees 的单位“转换”为普通的 degrees 单位:

double latitue_in_degrees = (double)latitude * 180.0 / exp2(23);

注意there are problems with floating point types。

C 中 float 数据类型的结构(二进制格式)是什么? 如何在 C 中找到有关 float 数据类型的信息? 我的意思是这种类型的位结构(十进制、信号指示符等)?

float 类型的确切格式取决于您的编译器 - 它可以是任何东西。那么,绝大多数今天的系统/编译器使用 binary32 格式,来自 IEC 754 标准的 float 数据类型。有关数据类型的确切格式,请参阅标准和无尽的网络资源。例如this converter is just fun to use。

【讨论】:

您好,您从定点到浮点的转换仅在未设置第 24 位时有效。否则需要反转2个补码(负数) 哦,你完全正确!我想我可以data[0]&lt;&lt;24 然后/ 256【参考方案3】:

通常为此目的使用位字段。你可以试试这样的:

#pragma pack(1)
typedef struct 
    union latitude
        uint32_t value : 24;
        struct octets
            uint8_t octetOne : 8;
            uint8_t octetTwo : 8;
            uint8_t octetThree : 8;
        
    
    union longitude
        uint32_t value : 24;
        struct octets
            uint8_t octetOne : 8;
            uint8_t octetTwo : 8;
            uint8_t octetThree : 8;
        
    
 frame;

然后将传入数据存储在此结构中并通过以下方式访问所需的值: frame.longitude.value

【讨论】:

如果结构声明中没有强制填充,映射可能不起作用。 #pragma pack(1) 是微软特定的编译指示。 Usually for such purposes bit fields are used 的代码针对一个特定的编译器和体系结构,它支持以特定的方式将字段打包到存储单元中。遗憾的是,位域在机器和编译器之间不可移植,位掩码是首选。 您的建议假设在运行代码的机器上,value 的 msb 将具有内存中的最低地址。这不是你总能期待的(字节序问题)

以上是关于C中浮点数据类型的结构(二进制格式)是啥?的主要内容,如果未能解决你的问题,请参考以下文章

c语言里面的float是啥意思

浮点型是啥意思

在python中 float是啥意思?

C#decimal是啥类型以及它的作用

bool是啥类型?

C语言中的datatype是啥