将一个 32 位浮点数转换为两个 16 位 uint 数,然后再次转换回该 32 位浮点数
Posted
技术标签:
【中文标题】将一个 32 位浮点数转换为两个 16 位 uint 数,然后再次转换回该 32 位浮点数【英文标题】:Convert one 32bit float number into two 16bit uint number and then convert back to that 32bit float again 【发布时间】:2014-09-24 08:44:13 【问题描述】:我正在将一个 32 位浮点数从一个平台转移到另一个平台。好吧,它只允许将 16 位 unsinged int 成员传递给传输寄存器。我在想我可以将 32 位浮点数分成两个 16 位,然后再转换为另一侧的 32 位。
(我用的是C语言)
喜欢:
float A = 3.14
uint16_t B = A & 0xffff;
uint16_t C = A & 0xffff0000;
float D = C<<16 & B;
显然这是不正确的,因为浮点数据在分配时将转换为无符号整数。那我平时应该怎么做呢?应该有一些相当成熟的方法来做类似的事情
谢谢
【问题讨论】:
如果您想进一步研究,只需提及一些关键字:这称为类型双关或重新解释。 【参考方案1】:您可以为此使用联合,例如:
typedef union
float f;
uint16_t a[2];
U;
U u;
u.f = 3.14f;
printf("%g -> %#x %#x\n", u.f, u.a[0], u.a[1]);
LIVE DEMO
注意:严格来说这是未定义的行为,但它是一种广泛使用的技术,它不太可能失败。或者,您可以采用更安全但可能效率较低的方法,只使用 memcpy,如下所示:
float f = 3.14f;
uint16_t a[2];
memcpy(a, &f, sizeof(a));
printf("%g -> %#x %#x\n", f, a[0], a[1]);
LIVE DEMO
【讨论】:
虽然这是常用的,但读取另一个联合成员而不是写入的联合成员是未定义的行为。 @vlad_tepesch:是的,谢谢,只需在答案中添加一个关于此的注释。 也许更好地使用中间 uint32_t 并手动屏蔽/合并 16 位片段以帮助解决字节顺序差异。毕竟号码是在“平台”之间转移的。 未定义的行为只是一个意外。它是在 C90 中实现定义的,在 C99 中明确未定义,但在 TC3(参见 DR 283)和 C11 中已修复。这里的标准有点模糊(类似的缺陷报告DR 236中有一些链接到委员会的讨论,为什么很难更明确地定义它),但意图很明确,编译器一直支持它。跨度>以上是关于将一个 32 位浮点数转换为两个 16 位 uint 数,然后再次转换回该 32 位浮点数的主要内容,如果未能解决你的问题,请参考以下文章
SSE 内在函数:将 32 位浮点数转换为 UNSIGNED 8 位整数