在保留顺序的同时将浮点转换为unsigned int

问题描述 投票:2回答:3

我已经找到了很多关于将float转换为int的答案。

我只操纵正浮点值。我一直使用的一个简单方法是:

unsigned int float2ui(float arg0) {
    float f = arg0;
    unsigned int r = *(unsigned int*)&f;
    return r;
}

上面的代码运行良好但它无法保留数字顺序。顺序我的意思是:

  float f1 ...;
  float f2 ...;
  assert( ( (f1 >= f2) && (float2ui(f1) >= float2ui(f2)) ) ||
          ( (f1 <  f2) && (float2ui(f1) < vfloat2ui(f2)) ));

我试图使用具有相同结果的联合。任何的想法?我使用Homebrew gcc 5.3.0。

c floating-point ieee-754
3个回答
4
投票

你正在使用的代码,如写,具有不明确的行为。如果你想半移植地访问floats的表示(实现定义,定义良好,假定IEEE 754和浮点数和整数字节序匹配),你应该这样做:

uint32_t float2ui(float f){
    uint32_t r;
    memcpy(&r, &f, sizeof r);
    return r;
}

对于非负值,浮点值和表示之间的这种映射是保持顺序的。如果您认为它无法保持秩序,我们需要确切地看到您认为哪些值是反例。


3
投票

如果f1f2是浮点数,而f1 <= f2(int)f1(int)f2是有效的转换,那么(int)f1 <= (int)f2

换句话说,截断到整数类型永远不会交换顺序。

你可以用float2ui替换(int)arg0,检查了float是否在int的范围内。

请注意,如果截断的float值超出该类型的范围,则intfloatunsignedfloat的行为是不确定的。

您当前的代码 - 以某种方式将float内存表示为int内存 - 具有未定义的行为。甚至通过union进行打字也会给你实现定义的结果;特别注意sizeof(int)不一定与sizeof(float)相同。

如果你使用的是IEEE754单精度float,没有陷阱表示的32位2的补码int,转换的正值,一致的字节序,以及由NaN+-Inf表示的各种模式的一些余量,那么转换受到类型双关语是命令保留。


0
投票

使用union从float中提取位应该有效。如果c标准实际上支持这一点,则会有一些讨论。但无论标准如何,gcc似乎都支持它。我希望有太多的现有代码需要它,因为编译器可以删除支持。

将float放入int并保持顺序时,您必须注意一些事项。

  1. 有趣的价值观,如nan没有任何保留的命令
  2. floats存储为幅度和符号位,而ints是两个赞美(假设一个理智的架构)。因此,对于负值,您必须翻转除符号位之外的所有位
  3. 如果qazxsw poi和qazxsw poi在你的架构上没有相同的字节顺序,你还必须转换endianess

这是我的实现,在x64上使用float进行了测试

int
© www.soinside.com 2019 - 2024. All rights reserved.