我已经找到了很多关于将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。
你正在使用的代码,如写,具有不明确的行为。如果你想半移植地访问float
s的表示(实现定义,定义良好,假定IEEE 754和浮点数和整数字节序匹配),你应该这样做:
uint32_t float2ui(float f){
uint32_t r;
memcpy(&r, &f, sizeof r);
return r;
}
对于非负值,浮点值和表示之间的这种映射是保持顺序的。如果您认为它无法保持秩序,我们需要确切地看到您认为哪些值是反例。
如果f1
和f2
是浮点数,而f1 <= f2
,(int)f1
和(int)f2
是有效的转换,那么(int)f1 <= (int)f2
。
换句话说,截断到整数类型永远不会交换顺序。
你可以用float2ui
替换(int)arg0
,检查了float
是否在int
的范围内。
请注意,如果截断的float
值超出该类型的范围,则int
对float
和unsigned
到float
的行为是不确定的。
您当前的代码 - 以某种方式将float
内存表示为int
内存 - 具有未定义的行为。甚至通过union
进行打字也会给你实现定义的结果;特别注意sizeof(int)
不一定与sizeof(float)
相同。
如果你使用的是IEEE754单精度float
,没有陷阱表示的32位2的补码int
,转换的正值,一致的字节序,以及由NaN
和+-Inf
表示的各种模式的一些余量,那么转换受到类型双关语是命令保留。
使用union从float中提取位应该有效。如果c标准实际上支持这一点,则会有一些讨论。但无论标准如何,gcc似乎都支持它。我希望有太多的现有代码需要它,因为编译器可以删除支持。
将float放入int并保持顺序时,您必须注意一些事项。
nan
没有任何保留的命令floats
存储为幅度和符号位,而ints
是两个赞美(假设一个理智的架构)。因此,对于负值,您必须翻转除符号位之外的所有位这是我的实现,在x64上使用float
进行了测试
int