【问题标题】:extract bits from 32 bit float numbers in C从 C 中的 32 位浮点数中提取位
【发布时间】:2012-06-21 10:42:26
【问题描述】:

32 位使用 IEEE 格式以二进制表示。那么如何提取这些位呢? & 和 | 等按位运算不要对他们工作! 我基本上想做的是从opencv中的32位浮点图像中提取LSB 提前谢谢!

【问题讨论】:

标签: c opencv floating-point bit-manipulation ieee-754


【解决方案1】:
uint32_t get_float_bits(float f) {
    assert(sizeof(float) == sizeof(uint32_t)); // or static assert
    uint32_t bits;
    memcpy(&bits, &f, sizeof f);
    return bits;
}

从 C99 开始,标准保证联合技巧有效(前提是大小匹配),并且实现通常甚至在需要之前就保证了它。就个人而言,我不知道人们在其中看到了什么,我更喜欢这个。

如果您只需要 LSB,并且知道字节序,则可以直接访问浮点数的一个字节,无需任何 memcpy、联合或违反严格别名。

int lsb = ((unsigned char*)&f)[0] & 1; // little-endian
int lsb = ((unsigned char*)&f)[sizeof(float)-1] & 1; // big-endian

【讨论】:

  • +1(实际上,“联合技巧”并未定义为在基础 C99 中工作;保证其行为的语言已添加到 TC2 或 3 中)。
【解决方案2】:

您可以使用联合来安全地提取值 (demo):

union fi_t
{
    unsigned int i;
    float f;
};

fi_t fi;
fi.f = 1.5;
unsigned int i = fi.i;

(只是从不进行类型转换,这将调用可怕的 ftol,它可能使用 SSE2 转换为整数形式,或 FISTP,它不会产生您所追求的 IEEE 位)

【讨论】:

  • 我建议将联合设为 volatile 以增加安全性,因为这种联合技术在历史上相对于 C 标准一直处于不稳定的基础(另请参见下面 Stephen Canon 的评论)。在实践中,20 多年来,跨平台和工具链的“不稳定联合”方法并没有让我失望。
  • @njuffa:我实际上从来没有想过让它volatile,我通常只是按原样使用它,因为 Quake 使用了相同的方法,并且 Quake 似乎适用于每一个(桌面)计算环境为人所知:D
【解决方案3】:

老把戏:

float num = 0.5;
uint32_t binary_representation = *(uint32_t *)#

【讨论】:

  • 违反严格的别名,在某些编译器的高级优化中会失败
  • @SteveJessop 无论如何,您不应该手动处理浮点数。
  • 也许吧,但是“你不应该这样做,因为我认为你太愚蠢而不会弄乱花车”和“你不应该这样做,因为它会在发布版本中意外中断”:-)
  • @H2CO3 不应该由谁?
  • 我不是在抱怨高优化级别,我是在抱怨人们编写具有 UB 的代码,这表现为没有在高优化级别上工作。
【解决方案4】:
#include<stdio.h>
union abc
{
    float fo;
    unsigned int no;
};
int main()
{   
    union abc test;
    test.fo=36.5;
    unsigned int x=test.no;
    for( int i = 0; i < sizeof(float)*8; i++ )
    {
        printf("%d", x & 0x1);
        x = x >> 1;
    }

    return 0;
}

这是一种提取浮点数的方法!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    • 2020-09-04
    • 2011-12-14
    • 1970-01-01
    • 2014-02-07
    • 2010-12-12
    相关资源
    最近更新 更多