包装漂浮很长

时间:2011-01-10 19:11:03

标签: c bit-manipulation

我想把2个花车装进很长的路上。这样做的正确方法是什么?

5 个答案:

答案 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位不足以获得良好的浮点数。