I'm doing some serial communication and sending floating point numbers. I think I have my pointers correct, but don't know how to convert the 4 bytes that have been sent back to a digital floating point number. Is there an app that will take 8 hex numbers and display them in digital?
Alternatively, what is the representation of a floating point number in the C++ in the Arduino? How many bits in the mantissa and how many in the exponent?
For example, I see the bytes as transmitted as 46 BC 42 04, which if the IDE uses little endian, the full floating point hex number would be 0442BC46, which I think is 70.1
The exponent limit for a 4-byte (32 bits) floating point number is e+38. If 6 bits are reserved for the exponent, with one as the sign bit, the remaining 5 bits only get you to +31.
Am I thinking in decimal and missing some magic in getting more precision out of the bits available?
Communication is between two Arduinos. I realize I can do the ASCII string thing, or since I'm only interested in numbers from -30.00 to +130.99, I can x100 and send 16-bit integers, then convert back to FP in the receiving unit.
But I'd much rather do the "union" thing and use pointers to send the 4 bytes and then stick them back together with pointers in the receiving unit.
As an aside, a billion years ago I made my own floating point algorithms for a Z-80, which had two sets of swappable registers. It was fast, but precision was limited by the number of bits in each FP number. But I knew exactly which bits did what.
I've looked all over the web for a depiction of the bit assignments for an FP in the Arduino and I can't find one.
I am 80% sure the Arduino uses IEEE floating-point format. Technically it is the compiler and not the chip. The 8-bit Arduinos have no hardware support for floating point.
It is a very interesting format, suitable for a wide variety of calculations. There are a few "magic" numbers such as zero and NaN (not a number) which are useful to know about.
Dr_Quark:
I've looked all over the web for a depiction of the bit assignments for an FP in the Arduino and I can't find one.
Arduino UNO contains the ATmega328P MCU which does not contain 'Floating Point Unit (FPU)' hardware like the 80486 which contains a FPU to accelerate numeric calculation. When we declare a variable like this: float x = 0.15625;, the compiler consults the following template of Fig-1 known as IEEE-754/binary32 Standard to compute a 32-bit pattern (in hex it is: 0x3E200000) for the number 0.15625; the value is saved into four consecutive memory locations in little endianess (Fig-2, lower byte is stored in lower memory location). To see the details of manual calculation on how to arrive at the given bit pattern, please see attached file.
Figure-1:
Figure-2:
Codes : (to pint the content of Fig-2);
unsigned lon *ptr;
ptr = (unsigned long*) &x;
unsigned long m = *ptr;
Serial.print(m. HEX); //shows: 3E200000
Golam..., thanks, this is just what I was looking for. I find it a little odd, however, that the mantissa sign bit is separated from the unsigned part and that the exponent isn't signed (it must be, but from the graphics it appears to be "signed" by the -127 offset, which I interpret to be two's compliment).
If you are passing the four raw bytes of a float between machines that share a floating point format - two Arduinos for instance, you can simply reassemble them into a float using pointers and casting. In such an instance, the detail of what makes up the float representation is irrelevant.
If the machines don't share the same format, I'd be inclined to pass the numbers as text, although there may be simple endian issues that you can fix by swapping the byte order.
GolamMostafa:
We are living with "mystery numbers" -- 0, 1, 2, ..., 9 and is fine?
Actually I would be one of those barking at the union not being standard (but works in simple cases with GCC) and would just deal with the address of the float, cast as a byte to store the information in the right order.
I would also recommend for sake of documentation and clarity and possibly long term maintenance to explicitly use sizeof(float). That won’t take any run time cycle, so why not doing so...
wildbill:
If you are passing the four raw bytes of a float between machines that share a floating point format - ...the detail of what makes up the float representation is irrelevant.
If the machines don't share the same format, I'd be inclined to pass the numbers as text, although there may be simple endian issues that you can fix by swapping the byte order.
Dear Wild, so true, but then us newbies face the pointers/union learning curve which, in my case, has been steeper than it should be.
Awol, "excess 127"? What, are mathematicians becoming like physicists and cosmologists, needing names that veer toward the indecipherable?
Thanks to all. This whole thread has raised the level of discourse (not once has anyone said "post ALL your code") and has kept my interest!