简体   繁体   English

将IEEE 754压缩位流转换为float单精度

[英]Converting IEEE 754 packed bit stream into float single precision

I have a problem with converting unsigned long to Float single precision Here is my problem 我将unsigned long转换为Float单精度有问题这是我的问题

I need to communicate in floating point in my program, but all my internal variables are unsigned long, So the design we decided was such that everything will remain same,(in unsigned long) and once a float needs to be given to application, i will convert to float and pass it on. 我需要在程序中以浮点数进行通信,但是我所有的内部变量都是无符号长的,因此我们决定的设计是,一切都将保持不变(无符号长),一旦需要将浮点数赋予应用程序,我将转换为float并继续传递。

So all the variables will have a IEEE 754 bit stream according to 因此,根据以下所有变量,将具有IEEE 754位流:

Float converter 浮球转换器

Steps i follow : 我遵循的步骤:

  1. I get the value in char array 我得到char数组中的值
  2. I take the bits and copy into a unsigned long 我把这些位复制到一个未签名的long中
  3. While giving the data on function call, i typecast to float single precision. 在函数调用中给出数据时,我进行了类型转换以浮动单精度。

In debugger i see the same bit pattern (in buffers) for steps 1 &2 在调试器中,我看到步骤1和2的位模式相同(在缓冲区中)

In step 3 too, i see the same binary pattern, but the value is not interpreted as a float 在步骤3中,我也看到了相同的二进制模式,但该值未解释为浮点型

Input : 21.125 输入:21.125

  1. Binary : 01000001101010010000000000000000 二进制:01000001101010010000000000000000
  2. Hex : 0x41a90000 十六进制:0x41a90000
  3. Decimal: 1101594624 小数:1101594624

     Code: void ApplicationApi(void * DataPtr) { (*(float32*)((void*)DataPtr))= unsignedLong_val; } 

Result in application DataPtr * DataPtr = 1.101594624 * e9 应用程序中的结果DataPtr * DataPtr = 1.101594624 * e9

Am i missing something here or the type case worked ? 我在这里缺少什么吗?

A standard C way to reinterpret the bytes of an unsigned long as a float is: unsigned long float ,重新解释unsigned long字节的标准C方法是:

y = (union { unsigned long u; float f; }) { x } .f;

This code defines a compound literal that is a union, and it initializes the union with the value of x , which should be an unsigned long . 此代码定义了一个作为联合的复合文字,并使用x的值初始化该联合,该值应为unsigned long Then it accesses the f member of the union, which is a float . 然后,它访问并集的f成员,它是一个float This float value is assigned to y , which should be a float . float值分配给y ,它应该是float

Thus, assuming the declaration of ApplicationApi must remain the same and that the void *DataPtr it is passed is the result of converting a pointer to a float to a pointer to void , its definition could be: 因此,假设ApplicationApi的声明必须保持相同,并且传递的void *DataPtr是将指向float的指针转换为指向void的指针的结果,则其定义可以是:

void ApplicationApi(void *DataPtr)
{
    * (float32 *) DataPtr =(union { unsigned long u; float32 f; }) { unsignedLong_val } .f;
}

Notes about this code: 关于此代码的注释:

  • This requires that unsigned long and float32 have the same size. 这要求unsigned longfloat32具有相同的大小。
  • It is undesirable for unsignedLong_val to have file scope. unsignedLong_val具有文件范围是不希望的。 It would be preferable to pass it as a parameter. 最好将其作为参数传递。
  • There is no reason inherent in this code that DataPtr should be passed as a void * . 在此代码中没有内在的理由将DataPtr作为void *传递。 It could be passed as a float32 * . 它可以作为float32 *传递。

Notes about code leading up to this code: 有关导致该代码的代码的注释:

  • The way that the bytes have been assembled in the unsigned long may have endian issues. 字节以unsigned long汇编的方式可能存在字节序问题。
  • In C implementations that are currently rare, an unsigned long could have trap values that prevent it from being used to hold arbitrary bytes. 在当前很少见的C实现中, unsigned long可能具有陷阱值,从而无法将其用于保存任意字节。

About the C standard and reinterpreting bytes: 关于C标准并重新解释字节:

  • Reinterpreting bytes through a union is the result of C 2011 (N1570) 6.5.2.3 3, which says that an expression using the . 通过联合重新解释字节是C 2011(N1570)6.5.2.3 3的结果,该结果表示使用的表达式. operator and a member name has the value of the named member. 运算符和成员名称具有指定成员的值。 Note 95 of the standard indicates that this may be used to reinterpret bytes. 该标准的注释95指示可以用于重新解释字节。
  • Another supported way to reinterpret bytes is by converting a pointer to a pointer to a character type and using the new pointer to copy bytes, per 6.3.2.3 7. ( memcpy is sometimes used for this.) 另一种受支持的重新解释字节的方法是按照6.3.2.3 7.将指针转换为字符类型的指针,然后使用新指针复制字节(有时使用memcpy 。)
  • 6.3.2.3 7 defines this behavior only for pointers to character types. 6.3.2.3 7仅针对字符类型的指针定义了此行为。 For other types, the C standard generally does not define the behavior of converting a pointer to a pointer of another type and dereferencing the result. 对于其他类型,C标准通常不定义将指针转换为其他类型的指针并取消引用结果的行为。 Therefore, the behavior of code that does this is undefined. 因此,执行此操作的代码的行为是不确定的。 Even if it appears to work in a test, it may later fail due to compiler optimizations or other effects. 即使它看起来可以在测试中运行,但由于编译器优化或其他影响,它稍后可能也会失败。

Try with this cast : 尝试使用此演员表:

void ApplicationApi(void * DataPtr)
{
  *(float32*)DataPtr = *(float32*)unsignedLong_val;
}

You have to declare that the right value is a float value. 您必须声明正确的值是浮点值。
With your cast, the right value is an integer and the left value a float. 对于您的类型转换,右边的值是一个整数,左边的值是一个浮点数。 The compiler convert implicitly the integer to a float value. 编译器将整数隐式转换为浮点值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM