【问题标题】:Interpreting a 32bit unsigned long as Single Precision IEEE-754 Float in C将 32 位无符号长整数解释为 C 中的单精度 IEEE-754 浮点数
【发布时间】:2015-11-10 15:09:08
【问题描述】:

我使用的是 Microchip 的 XC32 编译器,它基于标准 C 编译器。

我正在从 RS485 网络上的设备读取一个 32 位值,并将其存储在一个无符号长整数中,我已将其类型定义为 DWORD。

typedef DWORD unsigned long;

就目前而言,当我将此值类型转换为浮点数时,我得到的值基本上是整数表示的浮点版本,而不是正确的 IEEE-754 解释浮点数。

DWORD dword_value = readValueOnRS485();
float temp = (float)dword_value;

在这里,dword_value 将以十六进制格式作为 0x4366C0C4 出现,作为十进制将表示为 1130807492,因此将其类型转换为浮点数只会给我 1.130807492*10^9 或 1130807492.0 这不是我想要的。

我想要单精度 IEEE-754 表示,它会给我一个浮点值 230.75299072265625

很明显,将类型转换为 float 对我不起作用。我需要一种可以将这种形式转换为我的方法。我在 XC32 库中找遍了,我找不到任何东西。

有没有人知道一种预定义的方法可以为我正确地进行这种解释?或者我可以写一些建议的方法吗?我试图避免为这个特定任务编写自己的代码,因为我担心如果 C 已经有这个函数,我找不到有效的解决方案。

有趣的是,如果我对 char* 执行此操作,则该 char* 上的值正确地表示为 230.75:

sprintf(random_char_pointer, "%.2f, dword_value);

此处将 random_char_pointer 打印到屏幕给我 230.75,因此 sprintf 必须为我正确处理解释。因此,我假设 C 中已经有一些东西适合我。有人可以帮忙吗?

【问题讨论】:

  • f = *(float*) &uvalue;(加/减对齐注意事项)
  • @joop 这不就相当于转换为float吗?
  • 不,我将一个 unsigned int pointer 转换为一个浮点 pointer 并取消引用它。
  • 没有标准的 C 编译器。 “基于标准 C 编译器”是什么意思?
  • 顺便说一句:这可能是 XY 问题。 为什么您将 4 字节块接收到 uint32_t 类型值中?由于 rs485 传输的基本单位是 8 位字符,你也可以将 4 个连续字节接收到一个 char data[sizeof floatval]; 对象中,并使用 memcpy(&floatval, data, sizeof data); 进行转换

标签: c precision point ieee-754


【解决方案1】:

推荐的方法是使用联合:

union {
    DWORD w;
    float f;
} wordfloat;

wordfloat.w = dword_value;
temp = wordfloat.f;

这符合 ISO 9899:2011 §6.5.2.3 ¶3 脚注 95 的要求:

后缀表达式后跟. 运算符和标识符指定结构或联合对象的成员。该值是指定成员的值,95) 如果第一个表达式是左值,则该值是左值。如果第一个表达式具有限定类型,则结果具有 指定成员类型的限定版本。

95) 如果用于读取联合对象内容的成员与上次用于在对象中存储值的成员不同,则将值的对象表示的适当部分重新解释为对象表示在 6.2.6 中描述的新类型中(有时称为“类型双关语”的过程)。这可能是一个陷阱表示。

【讨论】:

  • 谢谢 FUZxxl 会试试这个并告诉你
  • 我很好奇,volatile 的推荐来自哪里?能够进行这种数据重新解释是 C 中存在(普通、非易失性)union 的主要原因之一。
  • 不,不需要 volatile (基本上是荒谬的,因为两个成员共享相同的位置,缓存它们的值不会改变结果) IIRC 工会不保证两者成员实际共享完全相同的位置(两个成员的对齐或大小仍然可能不同,就像我的速记评论一样)
  • @joop 联合保证两个成员共享相同的内存,因为每个联合成员的地址比较等于联合的地址,因此每个成员都位于相同的地址。我虽然需要 volatile 来规避严格的别名规则,但显然不是。
  • 不错的答案,引用标准表示赞赏。
猜你喜欢
  • 1970-01-01
  • 2021-10-06
  • 2015-03-25
  • 2013-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
相关资源
最近更新 更多