虽然“我们都知道”x == y
可能有问题,但x
和y
是浮点值,这个问题更具体一点:
int x = random.Next(SOME_UPPER_LIMIT);
float r = x;
// Is the following ALWAYS true?
r == x
现在,由于float的范围远大于整数(但精度不足以在边缘处唯一地呈现整数),如果对此问题的回答< em>还解决了上述x
的哪些值可以保证,如果可以保证的话。
目前我的代码是做出这个假设(对于相对较小的x值) - 我想确保我不会被咬伤:)
这将失败,“不等于:16777217”(cast float - &gt; int):
for (int i = 0; i < int.MaxValue; i++) {
float f = i;
if ((int)f != i) throw new Exception("not equal " + i);
}
这个类似的代码不会失败(只有int - &gt; float);但是,由于转换中的丢失,有几个浮点数可以“等于”相同的整数,并且可能代表一个无声的错误:
for (int i = 0; i < int.MaxValue; i++) {
float f = i;
if (f != i) throw new Exception("not equal " + i);
}
答案 0 :(得分:13)
是的,无论int
是什么价值,比较都将是真实的。
int
将转换为float
进行转化,第一次转换为float
将始终提供与第二次转化相同的结果。
考虑:
int x = [any integer value];
float y = x;
float z = x;
y
和z
的值始终相同。如果转换失去精度,则两次转换都将以完全相同的方式失去精度。
如果您将float
转换回int
进行比较,那就是另一回事了。
另请注意,即使转换为int
的特定float
值始终会产生相同的float
值,但这并不意味着float
值具有对于int
值是唯一的。有int
个值(float)x == (float)(x+1)
为true
。
答案 1 :(得分:5)
以下实验表明,答案是你没有那种平等不正确的边缘情况
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;
}
转换似乎是合理的
float f = i;
和
if ((int)f != i)
应遵循相同的规则。这证明了int - &gt;浮动和浮动 - &gt; int转换是一种双射。
注意:实验代码实际上没有测试边缘情况int.MaxValue,因为Parallel.For的到参数是独占的,但我分别测试了该值并且它也通过了测试。
答案 2 :(得分:5)
比较int和float时,int隐式地转换为float。这确保了相同的精度损失,因此比较将始终为真。只要你不打扰隐式演员或算术,就应该保持平等。例如,如果你这样写:
bool AlwaysTrue(int i) {
return i == (float)i;
}
有一个隐式转换,所以它等同于这个函数应该总是返回true:
bool AlwaysTrue(int i) {
return (float)i == (float)i;
}
但如果你这样写:
bool SometimesTrue(int i) {
return i == (int)(float)i;
}
然后没有更多的隐式演员,精确度的损失只发生在右侧。结果可能是错误的。同样,如果你这样写:
bool SometimesTrue(int i) {
return 1 + i == 1 + (float)i;
}
然后双方的精确度损失可能不相等。结果可能是错误的。
答案 3 :(得分:3)
我运行此代码时没有抛出异常:
for (int x = Int16.MinValue; x < Int16.MaxValue; x++)
{
float r = x;
if (r != x)
{
throw new Exception("Failed at: " + x);
}
}
还在等待(没有完成这个测试,因为它花了太长时间,但在运行时从未引发异常):
for (long x = Int64.MinValue; x < Int64.MaxValue; x++)
{
float r = x;
if (r != x)
{
throw new Exception("Failed at: " + x);
}
}
退回并运行你的例子,但需要注意,这是输出:
[Exception: not equal 16777217 ?= 1.677722E+07 ?= 16777216]
for (int i = 0; i < int.MaxValue; i++)
{
float f = i;
if ((int)f != i) throw new Exception("not equal " + i + " ?= " + f + " ?= " + (int)f);
}
答案 4 :(得分:0)
我对浮点运算的理解是它们由CPU处理,它们只能决定你的精度。因此,没有确定的值,浮动失去精度。
我曾经认为x86架构保证了最低限度,但我被证明是错误的。