Floating Point Numbers

11 replies to this topic

#1 mityeltu

mityeltu

Regular

• EstablishedMember
• 86 posts
• Gender:Male
• Location:Tennessee
• Interests:Communications

Posted 01 August 2017 - 06:59 PM

```int i, f;
float fnum = 0x41bba752; // this should be 23.4567
i = float32_to int32(fnum);
lprintf("%d",i);
lprintf(".");
f = float32_to_int32(float32_mul(float32_sub(fnum,float32_from_int32(i)),10000));
lprintf("%d".f);
```

I am attempting to recombine a set of 4 bytes sent via I2c into a floating point number. I can see the 4 bytes being transferred using a logic analyzer and they are correct for the number I am transferring, but I can't get the recombined number to diaply correctly, so I tried to just load the floating point number as a hex value and I get garbage on the LCD.

Here's what I'm doing: see above (I guess - this thing never puts my code where I want it).

Anyway, the LCD shows -23040.-1 which is obviously wrong. So, why am I gettign such garbage? Any ideas?

If I use fnum = 23.4567, the LCD shows 23.4567. Maybe I did the conversion wrong, but Im pretty sure that 23.4567 = 0x41bba752.

#2 richardc

richardc

Newbrie

• EstablishedMember
• 19 posts
• Gender:Male
• Location:Gippsland VIC,Australia

Posted 02 August 2017 - 12:04 AM

float fnum = 0x41bba752; // this should be 23.4567

would that not yield
fnum=1,102,817,106

and it's not going to fit in an int

I would use a union to load a float from  a byte array

#3 Pavel

Pavel

Super Maniac

• 1,451 posts
• Gender:Male
• Location:Melbourne, Australia

Posted 02 August 2017 - 03:48 AM

`float fnum = 0x41bba752; // this should be 23.4567`

Use either this:

```asm
{
movlw 0x52
movwf _fnum+0
movlw 0xa7
movwf _fnum+1
movlw 0xbb
movwf _fnum+2
movlw 0x41
movwf _fnum+3
}```

or this:
```union
{
unsigned long l;
float f;
} f;
f.l = 0x41bba752;
fnum = f.f;```

#4 mityeltu

mityeltu

Regular

• EstablishedMember
• 86 posts
• Gender:Male
• Location:Tennessee
• Interests:Communications

Posted 02 August 2017 - 11:11 AM

I'll try both today.

Can anyone explain why my code doesn't work? I realize that an int is only 2 bytes, but the fact is a float is 4 bytes and if I load a float with the value 23.4567, the hex value stored in the variable should be 0x41bba752 based in IEEE. So, if I shift those bits into the variable, why do I get such strange results? As I said, if I load the variable with 23.4567 and then use the method listed above, the LCD will have 23.4567 on it, but when I shift the bits into the variable and perform the above function, the LCD gives me nonsense. Is there a reason for this that I am not understanding?

#5 mityeltu

mityeltu

Regular

• EstablishedMember
• 86 posts
• Gender:Male
• Location:Tennessee
• Interests:Communications

Posted 02 August 2017 - 11:26 AM

The Union worked!!

Thank you! I have no idea WHY it worked, but it worked. This is excellent! I now have a complete I2C LCD library that can receive any kind of variabel and display it on an LCD. Perfect!

I would still love to hear why my original code does not do the same thing.

Edited by mityeltu, 02 August 2017 - 11:26 AM.

#6 richardc

richardc

Newbrie

• EstablishedMember
• 19 posts
• Gender:Male
• Location:Gippsland VIC,Australia

Posted 02 August 2017 - 11:45 AM

maybe this will explain how 4 bytes are used to represent a fp number

https://www.h-schmid...er/IEEE754.html

as pavel indicated
0x41bba752 is a long = 1,102,817,106

a float is a pointer to 0x52,0xa7,0xbb,0x41 stored in 4 consecutive bytes

as a float 0x41bba752 = 0x4e83774f

Edited by richardc, 02 August 2017 - 11:52 AM.

#7 mityeltu

mityeltu

Regular

• EstablishedMember
• 86 posts
• Gender:Male
• Location:Tennessee
• Interests:Communications

Posted 02 August 2017 - 11:56 AM

I'm not sure how that is really any different. If I take a floating point variable and shift in 0x41bba752 and take a second floating point variable and load it with 23.4567, do they not contain the same hex values? That is really confusing if they would not be the same. I understand what you mean about the integer type value being very large, but if the bits in a float variable loaded with 23.4567 are in the same order as the one loaded with 0x41bba752, why do they produce different values?

Is it becuase of what you said above? "a float is a pointer... " So, somehow when a float is declared, the compiler knows to grab 4 bytes, but uses each byte differently than if the float is loaded with the same bit pattern in a different way? Why does that make any sense?

Wait, is it backwards? If I shift in the bits in reverse byte order, wil I get the correct value in the float?

Edited by mityeltu, 02 August 2017 - 11:58 AM.

#8 mityeltu

mityeltu

Regular

• EstablishedMember
• 86 posts
• Gender:Male
• Location:Tennessee
• Interests:Communications

Posted 02 August 2017 - 12:04 PM

What? "as a float 0x41bba752 = 0x4e83774f"?!  Wait.... I'm going to go do some research on this.... I obviously missed something in C training. I'll have to get back to you on this. That makes absolutely no sens at all to me. In fact, at the moment, that seems like a complete contradiction.

Not saying you're wrong. In fact, I'm saying you're probably right and I just don't understand. So, thank you for the correction, and I'm gonna go and relearn - or maybe just learn - what it is you;re talking about.

Thanks.

#9 richardc

richardc

Newbrie

• EstablishedMember
• 19 posts
• Gender:Male
• Location:Gippsland VIC,Australia

Posted 02 August 2017 - 12:05 PM

float fnum ; reserves 4 bytes and makes a pointer for a float structure

fnum = 23.4567; will convert 23.4567 to a floating point representation and store it
like this 0x52 @fnum,0xa7 @fnum+1,0xbb@fnum+2,0x41@fnum+3

fnum = 0x41bba752; will convert 1,102,817,106 to a floating point representation and store it
like this 0x4f @fnum,0x77 @fnum+1,0x83@fnum+2,0x4e@fnum+3

#10 richardc

richardc

Newbrie

• EstablishedMember
• 19 posts
• Gender:Male
• Location:Gippsland VIC,Australia

Posted 02 August 2017 - 12:16 PM

Wait, is it backwards? If I shift in the bits in reverse byte order, wil I get the correct value in the float?

no

did you look at the link I gave you ?

plug some numbers in it , see for yourself how numbers are represented as exponent and mantissa
when floating point vars are used .

#11 Pavel

Pavel

Super Maniac

• 1,451 posts
• Gender:Male
• Location:Melbourne, Australia

Posted 02 August 2017 - 11:00 PM

When you assign an integer to a float like in float fnum = 0x41bba752; you expect compiler to do copy number into the float directly byte by byte. This is not what's happening. Behind the scene compiler generates code like fnum = float32_from_int32(1102817106); so you get the same value but presented as a float.

#12 jartim

jartim

Newbrie

• Members
• 2 posts

Posted 14 August 2017 - 09:30 PM

I would guess the endian-ness is wrong for the long-integer so when you load the bytes in individually, they're actually going in in the wrong order.  The union works because the compiler automatically swaps the bytes around to match the correct endian-ness for the long or float.