How to covert 4 bytes to float?

Eleckits:
this is the code from proton pic basic it is sending float value 4.55 via serial then I see it on LCD as Hex as :

9A991181

Dim SerData As Float 

Main:
SerOut PORTA.2, 396, [SerData]
SerData = 4.55
Print At 1,1, Hex SerData
DelayMS 2000
Cls
GoTo Main





so could you please tell me what is the problem?

Then the received bit stream is not an IEEE-754 standard. Ask the instrument/sensor manufacturer about the coding scheme of the binary data.

so could you please tell me what is the problem?

There's something wrong with "proton pic basic" (whatever that is) ?

Float Value 4.55
Hex Value 0X9A991181
Binary of float bytes that sent from proton pic basic as :

byte0 = 10000001
byte1 = 10001
byte2 = 10011001
byte3 = 10011010

byte0 = 10000001
byte1 = 10001
byte2 = 10011001
byte3 = 10011010

byte0 = 0x81
byte1 = 0x11
byte2 = 0x99
byte3 = 0x9a

Are we convinced this device uses IEE754?

This converter shows converting 4.55 to hex value as : 8111999A

please check picture

float to hex.png

I checked the picture - you circled the wrong part.

Try the PIC pro basic forum.

Are we convinced this device uses IEE754?

IEE754 or IEEE754?

I want to send float value via serial from pic to esp8266

please check picture of proteus testing

GolamMostafa:
IEE754 or IEEE754?

I'm more used to typing IEE than IEEE.
Post nominals, and all that.

Eleckits:
This converter shows converting 4.55 to hex value as : 8111999A

please check picture

As AWOL said, you circled the wrong number.

PieterP:
No it's not. 4.55 as a 32-bit IEEE754 floating point number is 0x4091999a.
Also mind the Endianness.

If the PIC really prints those 0x81 etc. bytes, then there is a problem with that code, not with the receiving Arduino code.

I think you can use a union to do this despite it being "against the rules", as long as that's all you use the union for. If you use a union to store a bunch of different types of different sizes to, say, save memory usage then, yes, you're going to get unpredictable results if you switch active members randomly.

If you create a union of a float type and a byte-array of size sizeof( float ) then you should be reasonably safe as long as you get the Endian-ness right.

TheMemberFormerlyKnownAsAWOL:
I'm more used to typing IEE than IEEE.
Post nominals, and all that.

There may be a reason behind typing of IEE instead of IEEE as IEE is a British Professional Organization; whereas, IEEE is an American Professional Organization. It could be that IEE has adopted IEEE-754 Standard and now it is IEE-754 for UK. For example, Bangladesh has adopted many British standards (BSXXXX) and all those are now named as BDSXXXX.

proton basic uses the microchip {ccs] 32bit fp format

fwiw

this python 2.7 script can convert between ccs and iee754

from ctypes import *
import array
import struct
import binascii




class ieeef(Structure):
    _fields_ = [
                ("fdata",c_float)]
    
class calf(Union):
    _fields_ = [("data", ieeef),
            ("hdata",c_ubyte *4 )]


class myunion(Union):
    _fields_ = [("real", c_float),
            ("hdata",c_ubyte *4 )]




    
 
def  str2barray(S):
    try:
       return bytearray.fromhex(S)
    except ValueError:
       return None
        


def  barray2str(B):
     return binascii.b2a_hex(B)


def ieee2ccs(d): #c_ubyte_Array
    #ieee74 bytearray to ccs(microchip float)
    j  = bytearray(d)
    sb=j[3]&128
    lse=j[2]&128
    j[3]&=127
    j[3]<<=1
    if lse :
        j[3]+=1
    if sb:
        j[2]|=128
    else:
        j[2]&=127
    return j


def ccs2ieee(j): #bytearray(j)
    #ieee74 bytearray  ccs(microchip float) to ieee74 bytearray 
    sb=j[2]&128
    lse=j[3]&1
    j[3]>>=1
    if lse :
        j[2]|=128
    else:
        j[2]&=127     
    if sb:
        j[3]|=128
    else:
        j[3]&=127
    return j




tp=myunion()
tp.real=4.55
print "as ieee",barray2str(tp.hdata)
print "as ccs",barray2str(ieee2ccs(tp.hdata))
print "value",tp.real

as ieee 9a999140
as ccs 9a991181
value 4.55000019073

Blackfin:
I think you can use a union to do this despite it being "against the rules", as long as that's all you use the union for.

Else, one has to go with the following cryptic codes which are not practically liked by the pupils:

float y;
long *ptr;
ptr = (long*)&y;
*ptr = 0x4091999A;
Serial.print(y, 2);   //shows: 4.55

GolamMostafa:
There may be a reason behind typing of IEE instead of IEEE as IEE is a British Professional Organization;

As I suggested, I am more accustomed to typing "IEE", because I most often type those letters as post nominals.
That's the reason.

Blackfin:
I think you can use a union to do this despite it being "against the rules", as long as that's all you use the union for. If you use a union to store a bunch of different types of different sizes to, say, save memory usage then, yes, you're going to get unpredictable results if you switch active members randomly.

If you create a union of a float type and a byte-array of size sizeof( float ) then you should be reasonably safe as long as you get the Endian-ness right.

I don't understand how there can still be a discussion about this.
If you use unions or pointer aliasing for type punning, your code is simply ill-formed. Period. It violates the standard, and you have no guarantee whatsoever that it will still work tomorrow.

I don't see why using a union to store a bunch of different types of different sizes would be bad, and using it for type punning would be perfectly fine.
If you can back up this claim using concrete evidence from the standard, I'll gladly change my views, but please, spreading misinformation doesn't help anyone.

GolamMostafa:
Else, one has to go with the following cryptic codes which are not practically liked by the pupils:

float y;

long ptr;
ptr = (long
)&y;
*ptr = 0x4091999A;
Serial.print(y, 2);   //shows: 4.55

As mentioned before, this code is not valid either. See reply #12 and #14

The only valid solution I'm aware of, and the one that's encouraged by the C++ Core Guidelines is to use a memcpy, which is, in my eyes, a perfectly sensible solution, you're using the memory contents of one object for another object.
If you're worried about the overhead caused by memcpy, don't be, compiler designers are aware of this use of the function, and will optimize it out in pretty much all cases.

Check out this on the Compiler Explorer: Compiler Explorer

#include <stdint.h>
#include <string.h>

// See ยงC.183 of the C++ Core Guidelines
// https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Ru-pun

// Good: using memcpy
float bytesToFloat(uint8_t (&bytes)[4]) {
    static_assert(sizeof(float) == 4, "float size expected to be 4 bytes");
    float result;
    memcpy(&result, bytes, 4);
    return result;
}

// BAD! Don't do this, type punning using a union is not allowed
float bytesToFloatUnion(uint8_t (&bytes)[4]) {
    union {
        uint32_t u32;
        float f;
    } u;
    u.u32 = ((uint32_t) bytes[0] << 0) 
          | ((uint32_t) bytes[1] << 8)
          | ((uint32_t) bytes[2] << 16)
          | ((uint32_t) bytes[3] << 24);
    return u.f;
}

// BAD! Don't do this, it breaks the strict aliasing rule
float bytesToFloatAliasing(uint8_t (&bytes)[4]) {
    float result;
    uint32_t* const py = (uint32_t*) &result;
    *py = ((uint32_t) bytes[3] << 24) |
          ((uint32_t) bytes[2] << 16) |
          ((uint32_t) bytes[1] << 8) |
          ((uint32_t) bytes[0] << 0);
    return result;
}

As you can see, the three functions compile to the exact same machine code when optimizations are enabled. In this case, the memcpy version obviously wins, because it's the only valid one, it's just as fast as the other two, and it has the least amount of code.

Even when optimizations are turned off using -O0 (why would you do that?), the memcpy version boils down to 35 instructions, the union version to 83 (!) instructions, and the pointer aliasing version to 93 (!) instructions.
Clearly, memcpy wins here as well, it's almost three times faster than the pointer version, and more than two times faster than the union version.

If you tune down optimizations for debugging, using -Og, the memcpy version is optimized entirely, it's just 5 instructions, while the union and pointer versions aren't optimized: 46 and 43 instructions respectively.
In this case, the memcpy version is 9 times faster.

This optimization is possible because you're telling the compiler exactly what you want to do, instead of hiding it behind obscure pointer manipulations or union abuse.

I really hope we can finally settle this, too much bad code has been promoted already.

TL;DR
Using unions or pointer aliasing for type punning is illegal.
Using memcpy is the only valid option, and on top of that it is much faster than the other two, and the code is shorter and more readable.

you have no guarantee whatsoever that it will still work tomorrow

True, but since it has been implemented and worked for decades with avrgcc, it is extremely unlikely that the developers will change that tonight.

I'm tired of these religious arguments.

jremington:
True, but since it has been implemented and worked for decades with avrgcc, it is extremely unlikely that the developers will change that tonight.

How is that a sensible argument? Arduino and C++ support many platforms, and some of them come with a custom toolchain. Apart from the undefined behavior, I presented enough other reasons to prefer memcpy over the other two.

jremington:
I'm tired of these religious arguments.

Violating the standard is not religious. A piece of code is either allowed, or it's not.
And I don't think measurable performance differences are religious either.

is there any solution?

Yes - contact the PIC Pro Basic support desk, or research their FP representation