C++ 无法将浮点值保存到位字段结构

C++ 无法将浮点值保存到位字段结构,c++,c,C++,C,我有一个结构 struct { u32 var1 :7; u32 var2 :4; u32 var3 :4; u32 var4 :1; u32 var5 :4; u32 var6 :7; u32 var7 :4; u32 var8 :1; } my_struct; my_struct struct1[10]; for(int i=0;i<10; i++) { // left some portion s

我有一个结构

struct {
   u32 var1 :7;
   u32 var2 :4;
   u32 var3 :4;
   u32 var4 :1;
   u32 var5 :4;
   u32 var6 :7;
   u32 var7 :4;
   u32 var8 :1;
        } my_struct;

my_struct struct1[10];

for(int i=0;i<10; i++)
  {
    // left some portion
    struct1[i].var5= x;// where x is a float value retrieved from a database with sqlapi++ asDouble()

    cout<<"Value of x from db is:\t"<<x;   // prints 0.1 if it is stored, prints 2.4 if 2.4 is fed

    cout<<"Value of x stored in struct1 is:\t"<<struct1[i].var5;   // prints 0 instead of 0.1, prints 2 instead of 2.4
  }
struct{
u32-var1:7;
u32-var2:4;
u32-var3:4;
u32-var4:1;
u32-var5:4;
u32-var6:7;
u32-var7:4;
u32-var8:1;
}我的结构;
我的结构1[10];

对于(int i=0;i您不能。浮点值的大小是32位,您当然不能将其存储在var5可用的4位中。其他28位是非常必要的。

var5
是一个4位无符号整数,可以保存值0..15(合理地假设
u32
是类似
无符号int
的同义词)

不能在其中存储小数。
0.1
0.8
将存储为
0
3.4
将存储为
3

如果你真的想要分数,你必须解决如何表示分数(定点算术)。

你不能将双精度(64位)存储到只有4位的字段中。你可以这样做:

struct {
   u32 var1 :7;
   u32 var2 :4;
   u32 var3 :4;
   u32 var4 :1;
   double var5;
   u32 var6 :7;
   u32 var7 :4;
   u32 var8 :1;
        } my_struct; 
还是这样

struct {
   u32 var1 :7;
   u32 var2 :4;
   u32 var3 :4;
   u32 var4 :1;
   u64 var5 :64;
   u32 var6 :7;
   u32 var7 :4;
   u32 var8 :1;
        } my_struct; 
  ..

  struct1[i].var5 = *(u64*)&x; // reinterpret the double as a memory array of 8 bytes
第二种方法不推荐


如果您想在4位中存储64位,请阅读浮点(IEEE)的工作原理。

您不能在位字段结构中存储浮点值。浮点必须遵守特定的标准(IEEE 754)指定表示形式的。这些表示形式适用于x86上的32位和64位。因此位字段没有必要的空间来正确表示浮点值


位域必须是有符号或无符号整数。

您可以通过几个中间步骤来完成要求的操作。首先将浮点值转换为整数,然后将该整数转换为二进制表示形式。从那里,您可以将结果值分配给位域。此答案仅针对中间步骤

该信息提供了背景信息并证实了
5.2 float
0100000101001100110
表示。将float分解为二进制表示可以采用多种不同的方式。这只是一种实现或表示。颠倒此过程(即从二进制返回到float)将需要遵循链接中列出的相同规则,向后

注意:endian也是一个因素,我是在Windows/Intel环境下运行的

代码如下:

#包括/*printf*/
#包括/*strtol*/
常量字符*字节到二进制32(长整数x);
常量字符*字节到二进制64(uu int64 x);
int floatToInt(浮点a);
__int64双输入(双a);
内部主(空)
{
长吕瓦尔,纽因特;
__int64 longInt;
int i,len,数组[65];
int len1,len2,len3,len4,len5,len6;
char-buf[100];
char quit[]={”“};
浮点数fNum=5.2;
双dpNum=5.2;
长双浮球;
while(退出[0]!=“q”)
{
printf(“\n\n输入一个浮点数:”);
scanf(“%f”&fNum);
printf(“输入双精度数字:”);
扫描频率(“%Lf”、&ldFloat);
newInt=floatToInt(fNum);
{
//浮动
printf(“\n贷款:%6.7f\n”,fNum);
printf(“int:%d\n”,newInt);
printf(“二进制文件:%s\n\n”,字节\u到\u二进制文件32(newInt));
}
longInt=doubleToInt(dpNum);
{
//双重的
printf(“双精度:%6.16Lf\n”,ldFloat);
printf(“int:%lld\n”,longInt);
printf(“二进制文件:%s\n\n”,字节_到_二进制文件64(longInt));
/*字节到二进制字符串*/
sprintf(buf,“%s”,字节到二进制64(longInt));
}
len=strlen(buf);
对于(i=0;i0;z>>=1)//2^32
{
*p++=(x&z)?“1”:“0”;
}
返回b;
}
常量字符*字节到二进制64(\uuu int64 x)
{
静态字符b[65];//位加“\0”
b[0]='\0';
char*p=b;
无符号_uint64 z;
对于(z=9223372036854775808;z>0;z>>=1)//2^64
{
*p++=(x&z)?“1”:“0”;
}
返回b;
}
int floatToInt(浮点a)
{
返回(*(int*)&a));
}
__int64双精度输入(双a)
{
返回(*((u int64*)&a));
}
这是结果的图像(更新为32位和64位):


位域或无位域,
var5
的类型是
u32
(我假设它是某种无符号整数类型)。您希望如何在整数变量中存储浮点值?u32是什么类型,是浮点型还是整数型?@jodag:它必须是整数类型;这些是位域。为什么首先是位域(协议/硬件内容除外)?您知道浮点需要多少位吗?4位无符号位字段只能存储以下任何值:
0
1
2
3
4
5
6
7
8
9
10
11
12
/code>、
13,,
14
15
。我没有看到该列表中的
0.1
3.4
0.8
。您可以将浮点数存储在多个位中。但许多处理器使用32位,并且是CPU固有的。但是,如果遇到紧急情况,您可以对浮点数进行编码,但需要实现encoding你自己。你可以有更多的范围/精度(或更少),视情况而定。这不是真的。这只是一个广泛使用的规范。你可以为浮点数定义自己的表示形式。我曾经为6502A处理器做过一次(现在我显示了我的年龄!)。碰巧有很多处理器实现了它,但没有理由为浮点数定义自己的规范/表示形式,也没有理由自己实现运算符。@user1095108-我想念雷普顿和Elite。我不想念从磁带将它们加载到BBC B中的1/2小时(要填满32k!).我的手机上有32Gb!注意-这只是一个表示-其他表示可能是KS a
#include <stdio.h>      /* printf */
#include <stdlib.h>     /* strtol */

const char *byte_to_binary32(long int x);
const char *byte_to_binary64(__int64 x);
int floatToInt(float a);
__int64 doubleToInt(double a);

int main(void)
{
     long lVal, newInt;
     __int64 longInt;
    int i, len, array[65];
    int len1, len2, len3, len4, len5, len6;
    char buf[100];
    char quit[]={" "};
    float fNum= 5.2;
    double dpNum= 5.2;
    long double ldFloat;

    while(quit[0] != 'q')
    {
        printf("\n\nEnter a float number: ");
        scanf("%f", &fNum);
        printf("Enter a double precision number: ");
        scanf("%Lf", &ldFloat);

        newInt = floatToInt(fNum);
        {
            //float
            printf("\nfloat: %6.7f\n", fNum);  
            printf("int: %d\n", newInt);  
            printf("Binary: %s\n\n", byte_to_binary32(newInt));
        }
        longInt = doubleToInt(dpNum);
        {
            //double
            printf("double: %6.16Lf\n", ldFloat);  
            printf("int: %lld\n", longInt);  
            printf("Binary: %s\n\n", byte_to_binary64(longInt));  
            /* byte to binary string */
            sprintf(buf,"%s", byte_to_binary64(longInt));
        }
        len = strlen(buf);
        for(i=0;i<len;i++)
        {   //store binary digits into an array.
            array[i] = (buf[i]-'0');    
        }
        //Now you have an array of integers, either '1' or '0'
        //you can use this to populate your bit field, but you will
        //need more fields than you currently have.

        printf("Enter any key to continue or 'q' to exit.");
        scanf("%s", quit);
    }
    return 0;
}

const char *byte_to_binary32(long x)
{
    static char b[33]; // bits plus '\0'
    b[0] = '\0';
    char *p = b;  

    unsigned __int64 z;
    for (z = 2147483648; z > 0; z >>= 1)       //2^32
    {
        *p++ = (x & z) ? '1' : '0';
    }
    return b;
}
const char *byte_to_binary64(__int64 x)
{
    static char b[65]; // bits plus '\0'
    b[0] = '\0';
    char *p = b;  

    unsigned __int64 z;
    for (z = 9223372036854775808; z > 0; z >>= 1)       //2^64
    {
        *p++ = (x & z) ? '1' : '0';
    }
    return b;
}

int floatToInt(float a)
{
    return (*((int*)&a));   
}

__int64 doubleToInt(double a)
{
    return (*((__int64*)&a));   
}