3

I have a structure

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
  }

I want to store floating point values like 0.1, 3.4, 0.8 in var5. But i am unable to do so. Can somebody help me how could i fix this problem?

Majid Khan
  • 111
  • 2
  • 14
  • 1
    Bitfield or no bitfield, `var5` is of type `u32` (which I assume is some unsigned integral type). How exactly do you expect to store a floating point value in an integral variable? – Igor Tandetnik Sep 19 '13 at 20:03
  • what type is u32, is it floating point or integer? – jodag Sep 19 '13 at 20:04
  • 4
    @jodag: it must be an integer type; those are bit-fields. – Jonathan Leffler Sep 19 '13 at 20:06
  • Why bitfields in the first place (except for protocols/hardware stuff)? Do you understand how many bits a float requires? – Ed Heal Sep 19 '13 at 20:07
  • u32 is Unsigned Integer 32 bit. – Majid Khan Sep 19 '13 at 20:13
  • @MajidKhan - "You cannot get a quart into a pint pot." - http://en.wiktionary.org/wiki/you_can%27t_get_a_quart_into_a_pint_pot – Ed Heal Sep 19 '13 at 22:07
  • 1
    A 4-bit unsigned bit field can only store any of the following values: `0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12`, `13`, `14`, `15`. I don't see `0.1`, `3.4`, or `0.8` in that list. – Keith Thompson Sep 19 '13 at 22:19
  • The most straightforward solution is to declare `var5` as a `float` or `double`, *not* as a bit field. If that doesn't meet your requirements, you'll have to tell us just what those requirements are. – Keith Thompson Sep 19 '13 at 22:20

5 Answers5

5

You can do what you ask with a few intermediate steps. First convert your float to an int, then convert that int into a binary representation. From there, you can assign the resultant values to your bit field. This answer only addresses the intermediate steps.

The information here provides background and corroboration that 5.2 float is represented by 01000000101001100110011001100110. Decomposing a float into a binary representation can be done many different ways. This is only one implementation or representation. Reversing this process (i.e. going from binary back to float) would require following the same set of rules laid out in the link, backwards.

Note: endian is also a factor, I ran this in Windows/Intel environment.

Code:

#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));   
}

Output

enter image description here

ryyker
  • 22,849
  • 3
  • 43
  • 87
3

You can't. A float value is 32-bits in size you certainly can't store it in the 4-bits var5 has available to it. The other 28 bits are very necessary.

Goz
  • 61,365
  • 24
  • 124
  • 204
  • 1
    You can store a floating point number in a multitude of bits. But a lot of processors use 32 bits and is native to the CPU. But, if push comes to shove, you can encode a floating point number but you will need to implement the encoding yourself. You can have more range/precision (or less) as the case may be. – Ed Heal Sep 19 '13 at 20:11
3

var5 is a 4-bit unsigned integer that can hold values 0..15 (working on a reasonable assumption that u32 is a synonym for something like unsigned int).

You can't store fractional values in it. 0.1 and 0.8 would be stored as 0; 3.4 would be stored as 3.

If you really want fractions, you're going to have to work out how to represent them (fixed point arithmetic).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
2

You can't store a double (64 bits) into a field of only 4 bits. You can either do it this way:

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; 

or this way

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

The second way is not recommended.

If you want to store 64 bits in 4 bits, read up on how floating point (IEEE) works. http://en.wikipedia.org/wiki/IEEE_floating_point

Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
  • Thanks a lot for help. Actually i was missing something. The value was supposed to be taken as float from user and a corresponding scaling factor was supposed to be given. For 0.8 it was 0.1. 0.8/0.1 passed in integer value which was stored in the bitfield. – Majid Khan Sep 26 '13 at 13:35
  • Your original code had only 4 bits for `var5`, so that means you can encode 0.0 to 1.5 in steps of 0.1, but you can't encode 3.4 (see your original post). – Mark Lakata Sep 26 '13 at 17:04
0

You cannot store a float value in a bit-field structure. Floats have to adhere to a specific standard (IEEE 754) that specifies a representation. These representations are for 32 and 64 bits on x86. Therefore a bit field wouldn't have the necessary space to properly represent a floating point value..

Bit-fields muse be a signed or unsigned integer.

in70x
  • 1,170
  • 1
  • 10
  • 16
  • This is not true. It is just one specification that is widely used. You could define your own representation for floating point numbers. I did it once for a 6502A processor (now I am showing my age!). It just happens that lots of processors implement it but there is no reason for defining your own specification/representation for floating point numbers and implement operators yourself. – Ed Heal Sep 19 '13 at 20:40
  • @user1095108 - I do miss Repton and Elite. I do not miss the 1/2 hr loading them into the BBC B from tape (to fill up 32k!). I have 32Gb on my phone! – Ed Heal Sep 19 '13 at 22:25