What is the benefit of storing integer value over float value?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

What is the benefit of storing integer value over float value?

Jump to solution
2,439 Views
Amit_Kumar1
Senior Contributor II

Hi

I am storing some data on a SD card. I am facing problem in storing float values as FATFs doesn't support floating point. Although I tried storing it in an array and printing on the SD card but it didn't worked. Is there any way of storing this in SD card without changing its data type to int? I cant use string as the data size will increase if I do so. I was wondering what are the benefit of using integer (multiply the floating point with 10^6 and change it to int) over floating point numbers.?

fps.jpg

Kind Regards

Amit Kumar

1 Solution
1,808 Views
BlackNight
NXP Employee
NXP Employee

Hello,

you can store any values as binary values, e.g.

FAT1_write(&fp1, myFloatVar, sizeof(myFloatVar), &bw); // Writing floating point variable to dis

But you need to take care you you will read it. That means that the reader has the same bit mapping (IEEE32/64) of the floating point bits (and e.g. not using a DSP float or similar).

As well you have to take care about the byte ordering (little/big endian). As long as e.g. you write that with a Kinetis, and read it with a Kinetis, you are fine.

Writinig it as a string value (sprintf()) and reading it as string (sscanf()), you are portable. But of course this representation needs more space (and time).

I hope this helps,

Erich

View solution in original post

0 Kudos
Reply
7 Replies
1,808 Views
razed11
Contributor V

Depending on your needs you may wish to consider implementing something like JSON or Google Protocol Buffers. This would allow your data to be more readily consumed by other platforms. For instance if you were to pull an SD card from a system and plug it in to a computer you could use Python or Ruby or C/C++ to read the data.

1,809 Views
BlackNight
NXP Employee
NXP Employee

Hello,

you can store any values as binary values, e.g.

FAT1_write(&fp1, myFloatVar, sizeof(myFloatVar), &bw); // Writing floating point variable to dis

But you need to take care you you will read it. That means that the reader has the same bit mapping (IEEE32/64) of the floating point bits (and e.g. not using a DSP float or similar).

As well you have to take care about the byte ordering (little/big endian). As long as e.g. you write that with a Kinetis, and read it with a Kinetis, you are fine.

Writinig it as a string value (sprintf()) and reading it as string (sscanf()), you are portable. But of course this representation needs more space (and time).

I hope this helps,

Erich

0 Kudos
Reply
1,808 Views
Amit_Kumar1
Senior Contributor II

Thanks Erich.  I hope this will resolve my issue. I guess I was having problem in reading the values as the reader was giving some other values. I need to check the bit mapping as u stated .

One more query I had regarding this. Suppose I have an array of uint8_t which I am writing into the card. Can I write the floating point value by bit shifting directly? I.e

uint8_t buffer[4];

float a, b;

buffer[0] = (0xFF 00 00 00 & a)  >>24;

buffer[1] = (0x00 FF 00 00 & a)  >>16;

buffer[2] = (0x00 00 FF 00 & a)   >>8;

buffer[3] = (0x00 00 00 FF & a);

FAT1_write(&fp1, buffer, sizeof(buffer), &bw);

b = buffer[0]<<24  |   buffer[1]<<16   |   buffer[2]<<8   |   buffer[3];                       // To regain the value

will a = b ??

Regards

Amit Kumar

0 Kudos
Reply
1,808 Views
egoodii
Senior Contributor III

I know I will get skewered by 'purists' for this, but the 'most efficient' technique for working with 'multiple views' of a word is the 'union':

union{            //Any of three ways to look at a 32-bit number
floatfval;
uint32_tuval;
union{                //Byte/Word/Dword, little-endian

   struct{

uint16_t lo;
int16_t hi;

   } s16;

   struct{

uint8_t ll;
uint8_t lm;
uitn8_t hm;
int8_t hh;

   } s8;

   int32_t s32;

}val;

}scaled_f;

This lets the 'union' take care of big-endian/little-endian concerns.  I can pick up bytes from some pointer (such as into an SD or EtherNET buffer, in this case a 'big-endian' source)  thus:

scaled_f.val.s8.hh = *pu8Data++;
scaled_f.val.s8.hm = *pu8Data++;
scaled_f.val.s8.lm = *pu8Data++;
scaled_f.val.s8.ll = *pu8Data++;

And save the whole to a 'float' pointer:

     *fltptr = scaled_f.fval;

Or I can pick up a 'float':

     scaled_f.fval = floater;

And save to a word pointer:

     *uintptr = scaled_f.uval;

This keeps all the compiler 'type checking' happy while I work with the bits and bytes, AND confines the big/little-endian concerns to ONE typedef!

1,808 Views
BlackNight
NXP Employee
NXP Employee

yes, that should work.

I would write it as

buffer[0] = (uint8_t)(a>>24);

buffer[1] = (uint8_t)(a>>16);

buffer[2] = (uint8_t)(a>>8);

buffer[3] = (uint8_t)(a);

and

b = (buffer[0]<<24)  |   (buffer[1]<<16)   |   (buffer[2]<<8)   |   buffer[3];                       // To regain the value

(above assumes int is 32bit, btw).

Erich

1,808 Views
Amit_Kumar1
Senior Contributor II

Hi Erich

This method of storing floating point didn't worked for me

I tried the following

buffer[0] = (uint8_t)(a>>24);

buffer[1] = (uint8_t)(a>>16);

buffer[2] = (uint8_t)(a>>8);

buffer[3] = (uint8_t)(a);

my buffer size is greater than 4. the following result I got.  I tried using int also but the error was same.

fp.jpg

I somehow made it error free by changing the syntax but in that process the float became integer with floating values being skipped.

buffer[0] = (uint8_t)(a) >>24;

buffer[1] = (uint8_t)(a) >>16;

buffer[2] = (uint8_t)(a) >>8;

buffer[3] = (uint8_t)(a);

I removed the datatype and then tried again the above error appeared.

buffer[0] = (a>>24);

buffer[1] = (a>>16);

buffer[2] = (a>>8);

buffer[3] = (a);

Is there any other way to make it happen? as my buffer will be of around 100 bytes and the i/p to it will be all mixed it will be of varying data types

Kind Regards

Amit Kumar

0 Kudos
Reply
1,808 Views
razed11
Contributor V

Hi Amit,

You will need to study up a little more on the C programming language.

If a is of type float then the compiler will not allow a >> 8. A bitwise shift operator doesn't make sense for a float. This is why your first example did not work.

In your second try you first cast the float to an 8-bit integer and then shift it. This is legal but not what you want. If a is 1.125 the cast will convert this to the integer 1 and then shift the result--you are losing all your floating point information.

In the third example you are back to shifting a float.

A way to do this is to use a union. It tells the compiler that you'd like to interpret a piece of memory as different data types. In this case you have four bytes that you want to interpret as either a float or a 32-bit unsigned number.

void test(void)

{

    uint8_t buffer[4];

    union

    {

        float f;

        uint32_t i;

    } u;

    u.f = 1.125;

    buffer[0] = (uint8_t)(u.i>>24);

    buffer[1] = (uint8_t)(u.i>>16);

    buffer[2] = (uint8_t)(u.i>>8);

    buffer[3] = (uint8_t)(u.i);

}

If in your buffer you are mixing types then you have other issues to deal with. How do you know how to decode your stream of bytes? If you have mixed data but it is the same each time I would define a struct that hold these and then write the structure out as raw binary. You'll need to understand how the data is packed which gets in to advanced territory but would look something like (does this editor have the ability to quote code???):

void test_2(void)

{

    struct

    {

        float f;

        uint32_t u32;

        uint8_t b;

    } frame;

    frame.f = 1.125;

    frame.u32 = 0xDEADDEED;

    frame.b = 0xAB;

    //write_to_device(&frame, sizeof(frame));

}

There are a lot of details to get right when doing stuff like this. You'll have to spend a lot of time working to understand it.

0 Kudos
Reply