我想把2个花车装进很长的路上。这样做的正确方法是什么?
答案 0 :(得分:5)
稍微取决于你想要它的可移植性,从两个方面来说:它完全适用于什么平台,以及它给出相同答案的平台。但是这样的事情。
#include <stdint.h>
long long pack(float lo, float hi) {
assert(sizeof(float) == 4);
assert(sizeof(long long) == 8);
assert(CHAR_BIT == 8);
uint32_t target;
memcpy(&target, &lo, sizeof(target));
long long result = target;
memcpy(&target, &hi, sizeof(target));
result += ((long long)target) << 32;
return result;
}
在一次写入+读取中将浮点数作为整数获取的“其他”方法是使用所谓的“联合强制转换”,但我更喜欢memcpy。您也可以一次访问一个unsigned char
个浮点数,并以8位移位建立long long
。
答案 1 :(得分:3)
你不能这样做。浮点数为32位宽,因此只有一个浮点数适合uint32_t
。
对于您编辑过的问题,根据您的编译器对严格别名优化的热情程度,您可以做类似的事情。但是一定要测试,因为编译器喜欢打破这种事情。更安全的实现可能会使用memcpy
。
#include <stdint.h>
union converter { uint32_t i; float f; };
uint64_t pack(float a, float b) {
union converter ca = { .f = a };
union converter cb = { .f = b };
return ((uint64_t)cb.i << 32) + ca.i;
}
void unpack(uint64_t packed, float *a, float *b) {
union converter ca = { .i = packed };
union converter cb = { .i = packed >> 32 };
*a = ca.f;
*b = cb.f;
}
注意:使用[u]int64_t
,而不是long long
;不能保证long long
正好是64位。
答案 2 :(得分:3)
假设您的浮点数使用32位表示,通常您将无法在不丢失数据的情况下执行此操作。
如果您必须这样做,您可能希望将它们转换为16位浮点数(又名“half”)http://en.wikipedia.org/wiki/Half_precision_floating-point_format
维基百科页面包含一个链接(位于最底部),提供有关如何在C中进行转换的信息。
一旦你有'一半',你可以咬一下&amp;将它们转换为32位整数。
更新,现在该问题已更改为“long long”而不是uint_32:
已经提到了memcpy解决方案,这是一个使用union的示例:
#include <stdio.h>
#include <stdint.h>
typedef union
{
uint64_t llv;
float fv[2];
} conv ;
int main(int argc, char **argv)
{
conv a;
conv b;
a.fv[0] = 1.0;
a.fv[1] = -2.0;
printf("%f %f\n",a.fv[0],a.fv[1]);
b.llv = a.llv;
printf("%f %f\n",b.fv[0],b.fv[1]);
}
答案 3 :(得分:2)
尝试以下方法:
void *float1_bits = &float1;
void *float2_bits = &float2;
long long packed_floats = (*(long long*)float2_bits << 32) | (*(long long *)float1_bits);
答案 4 :(得分:1)
标准的float和double是4和8个字节,因此你不能将它们中的两个直接打包成一个int 32 对象,因为它只有4个字节。
但是,您可以定义具有有限精度和指数范围的16位格式。 (我没有检查是否已经有标准。可能有,但这更有趣。)
f e d c|b a 9 8|7 6 5 4|3 2 1 0
S E E E|E E m m|m m m m|m m m m
我的新格式名为Ross-float,有一个符号位,5位指数和10位精度。
这种格式可以精确地表示从-1023到+1023的整数,它可以表示大约10 -4.8 到10 4.8 范围内的实数。
的更新强> 的
好的,现在问题已经改为 long long ,所以整个问题变得微不足道。这也是一样,因为16位不足以获得良好的浮点数。