当将两个float32表示为int32或uint32(使用union或casting指针类型)时,在有限的范围内(0..1),这些值是否可以相互比较,这将匹配作为浮点数执行时的比较结果?
范例:
int float_as_int(float f) {
union { int i; float f; } u;
u.f = f;
return u.i;
}
/* Assert the following is always true for values in a limited range. */
void assert_compare_works_as_expected(float a, float b) {
assert(float_as_int(a) < float_as_int(b) == a < b);
}
/* Psudocode */
int main() {
for f in 0..1 {
assert_compare_works_as_expected(f_prev, f);
f_prev = f;
}
}
字符串
如果不是,什么浮点数范围直接Map到int,以便可以进行比较?
7条答案
按热度按时间s2j5cfk01#
详细的答案是:是的,但有多个限制和警告。将
0
到1
范围内的浮点数作为整数进行比较在许多情况下可能会产生正确的结果。事实上,值不需要限制在此范围内:float
类型具有32位单精度IEEE-754表示,而int
类型具有32位2的补码表示,没有填充位(即int
是int32_t
);float
的值都不是NaN;float
和int
表示在内存中具有相同的字节序;int
进行比较将产生正确的结果,除非您正在比较+0.0
和-0.0
。int
的比较可能确实会产生正确的结果,但C标准并不保证,并且在大多数情况下,将float
的值作为int
访问违反了严格的别名规则。关于你的问题:某些整数值实际上可以具有与
int
和float
相同的表示,特别是0
,但浮点值-0.0
具有不同的表示,但与float
相比等于0.0
。只有两种其他特殊情况的整数具有与int32_t
和IEEE相同的表示。754float
:1318926965
(0x4E9D3A75
)和-834214802
(0xCE46E46E
)。您可以在这里查看IEEE格式的浮点值的实际表示,这是非常常见的,但不是C标准所要求的:
对于您的特定情况,如果您知道值在
0
到1
的范围内,您应该处理的唯一特殊情况是负0
。您可以通过屏蔽值将符号设置为正数,代码如下所示:字符串
g6ll5ycj2#
我解释你的问题的方式是:当将内存中浮点数的位模式解释为int时,通常的比较运算符对浮点数和整数的行为是否相同。
答案是否定的。严格地说,C标准有几种可能的整数表示法和更多可能的浮点数表示法。但即使限制我们自己到几乎每个人都做的-二进制补码整数和ieee 754 binary 32浮点数,答案仍然是否定的。
最简单的例子:浮点数有两个零。位模式0x 00000000和位模式0x 80000000表示数字0和-0。它们在浮点数时都比较相等,如果被解释为整数,它们就不会相等。然后你有两个无穷大,还有很多位模式表示NaN。
你可以列举特殊情况并避免它们,然后我很确定整数比较会起作用,但是无论你从整数比较中获得什么性能增益(我假设这是这里的重点),你都会在避免特殊情况时失去更多。
回应您的最后一次编辑:是的,在0到1的范围内,ieee 754浮点数的位模式是这样的,当被解释为整数时,普通的整数比较运算符将按照你想要的方式工作。这是一个坏主意,但它会工作。
y3bcpkx13#
如果将0和1之间的32位浮点数转换为int/uint,它们是否可以进行比较(具有相同的结果)?
使用
union
可以比较float
的范围(0和1)和如果下面的所有列表都可以被保险。否则,一般的答案是否定的。它可能有效,也可能无效。
字符串
float
是binary321.整数类型没有填充。(例如:
(u)intN_t
)类型。1.整数可以是任何编码:2的补码,1的补码,符号幅度
1.这个整数和
float
有相同的字节序。C不需要这个。1.整数/FP类型的大小是相同的。(这是在问题中暗示的)。
这也适用于[+0.0...+INF]的扩展范围。它不适用于-0.0。
为了比较2 any 有限/无限
float
,给定相同的endian-ness,预期的float
编码和上述条件:型
这对于需要执行FP比较的嵌入式应用程序很有用,但对于其他FP运算则不适用。
通常,由于抗锯齿,造型是UB。
hec6srdp4#
答案第一
是的,您可以比较
float
的二进制表示,只要它们使用IEEE-754格式,整数是2的补码,您正在比较正值或正值与负值,并且正确处理特殊情况。Snippet on Ideone.com in C
解释
IEEE-754浮点数(4字节)具有以下结构:
字符串
该值被编码为
mantissa * 2 ^ exponent
。指数范围为0x00
到0xFF
,它表示值-127
到128
(0x7F
对应于0
)。尾数表示 * 一个二进制分数 *,小数的左边总是隐含
1b
。尾数的每一位表示2 ^ -(n+1)
的值,其中n
是从左边开始的一位的索引。尾数的最左边的位具有0.5
的值,左边第二位0.25
,左边第三位0.125
,等值
0.5
将具有尾数b0000...
(b1.0
)和指数0x7E
(-1
)。值
0.03
将具有尾数b1110...
(b1.1110...
)和指数0x79
(-6
)。这些值将存储为:
型
可以存储的最小值是
1.0 * 2 ^ -127
(尾数和指数的所有位都为零)。这是一个特殊情况,代表0
。指数值0xFF
是为NaN
和infinity
保留的。Floating point number representation的
如果使用
signed int
,则可以将负的float
值与正的signed int
值进行比较,因为符号标志存储在signed int
和float
的最高位中。您不能像这样比较两个负的float
值,因为int
的否定不是仅通过反转符号标志来完成的。lymnna715#
答案是肯定的,但条件是:
-0.0
、-inf
、nan
、-nan
。详细信息:
signed int
和unsigned int
都可以用于匹配比较。0-1
,0.0..FLT_MAX
和inf
可以比较。-0.0..-FLT_MAX
也可以比较,但总是有一个翻转的顺序,例如:assert(float_as_int(a) > float_as_int(b) == a < b);
个在这种情况下,可以比较表示为int的2x浮点数,得到相同的结果。
下面是一个证据,证明这是可行的:
C代码,测试完整的无符号浮点范围。
字符串
一个Python 3脚本,用
nextafterf
检查0-1之间的所有值,注意这很慢 (因此上面的C版本)。型
请注意,这里的其他答案说,这不会在所有情况下工作,我很想知道在这种情况下,在这个答案的例子会失败,(除了架构,其中float和int不是4字节的大小)。
omqzjyyz6#
根据我的理解,你想从内存中读取浮点数作为无符号/有符号整数,我会给你给予答案。
不能将
float
与signed
或unsigned
int(32位)进行比较。例如,
int
中的数字4
被表示为0x00000004
,而相同的数字4
以浮点数(根据IEEE 754标准)表示为0x40800000
。siv3szwd7#
无论你是将union中的uint与float进行比较,还是将float本身进行比较,都是一样的。
如果你有两个操作:
字符串