虽然"我们都知道" x == y可能有问题,但在哪里x和y是浮点值,这个问题更具体一些:
int x = random.Next(SOME_UPPER_LIMIT);
float r = x;
// Is the following ALWAYS true?
r == x
Run Code Online (Sandbox Code Playgroud)
现在,因为float 的范围远大于整数的范围(但是精度不足以在边缘处唯一地呈现整数),如果对这个问题的回答也解决x了上述哪些值可以保证的话会很好. ,如果它可以得到保证.
目前我的代码正在做出这个假设(对于相对较小的x值) - 我想确保我不会被咬掉:)
这将失败,"不等于:16777217"(cast float - > int):
for (int i = 0; i < int.MaxValue; i++) {
float f = i;
if ((int)f != i) throw new Exception("not equal " + i);
}
Run Code Online (Sandbox Code Playgroud)
这个类似的代码不会失败(只有int - > float); 但是,由于转换中的丢失,有几个浮点数可以"等于"相同的整数,并且可能代表一个无声的错误:
for (int i = 0; i < int.MaxValue; i++) {
float f = i;
if (f != i) throw new Exception("not equal " + i);
}
Run Code Online (Sandbox Code Playgroud)
Guf*_*ffa 13
是的,无论价值多少,比较都将是真实的int.
的int将被转换为一个float来进行转换,并且所述第一转换float将总是产生相同的结果作为第二个转换.
考虑:
int x = [any integer value];
float y = x;
float z = x;
Run Code Online (Sandbox Code Playgroud)
值y和z将始终相同.如果转换失去精度,则两次转换都将以完全相同的方式失去精度.
如果你将float返回转换为int比较,那就是另一回事了.
另请注意,即使int转换为特定值的值float始终产生相同的float值,也不意味着该float值必须对该值唯一int.有int值,其中(float)x == (float)(x+1)会true.
以下实验表明,答案是你没有那种相等不正确的边缘情况
static void Main(string[] args)
{
Parallel.For(int.MinValue, int.MaxValue, (x) =>
{
float r = x;
// Is the following ALWAYS true?
bool equal = r == x;
if (!equal) Console.WriteLine("Unequal: " + x);
});
Console.WriteLine("Done");
Console.ReadKey();
return;
}
Run Code Online (Sandbox Code Playgroud)
转换似乎是合理的
float f = i;
Run Code Online (Sandbox Code Playgroud)
和
if ((int)f != i)
Run Code Online (Sandbox Code Playgroud)
应遵循相同的规则.这证明int - > float和float - > int转换是一个双射.
注:实验代码实际上并不测试边缘情况int.MaxValue因为的Parallel.For的,以参数是排他的,但我单独测试的价值,同时也通过了测试.
比较int和float时,int被隐式地转换为float.这确保了相同的精度损失,因此比较将始终为真.只要你不打扰隐式演员或算术,就应该保持平等.例如,如果你这样写:
bool AlwaysTrue(int i) {
return i == (float)i;
}
Run Code Online (Sandbox Code Playgroud)
有一个隐式转换,所以它等效于这个函数应该总是返回true:
bool AlwaysTrue(int i) {
return (float)i == (float)i;
}
Run Code Online (Sandbox Code Playgroud)
但如果你这样写:
bool SometimesTrue(int i) {
return i == (int)(float)i;
}
Run Code Online (Sandbox Code Playgroud)
然后没有更多的隐式演员表,精确度的损失只发生在右侧.结果可能是错误的.同样,如果你这样写:
bool SometimesTrue(int i) {
return 1 + i == 1 + (float)i;
}
Run Code Online (Sandbox Code Playgroud)
那么精确度的损失可能在双方都不相同.结果可能是错误的.