gpt4 book ai didi

c# - 为什么将值存储在变量中会改变相等比较的结果?

转载 作者:太空狗 更新时间:2023-10-29 17:49:15 24 4
gpt4 key购买 nike

以下代码的输出:

var a = 0.1;
var count = 1;

while (a > 0)
{
if (count == 323)
{
var isZeroA = (a * 0.1) == 0;
var b = a * 0.1;
var isZeroB = b == 0;

Console.WriteLine("IsZeroA: {0}, IsZeroB: {1}", isZeroA, isZeroB);
}

a *= 0.1;
++count;
}


IsZeroA:假,IsZeroB:真

奇怪的是,当我调试时在 if (count == 323) 之后放置一个断点并在 Visual Studio Watch 窗口中放置表达式 (a * 0.1) == 0 ,它报告表达式为 true

有谁知道为什么表达式 a * 0.1 不为零,但是当分配给变量 b 时,b 为零?

最佳答案

我的特定硬件和 CLR 版本不会发生这种情况。 编辑: 哦,是的,如果我使用 “x86”(或启用“首选 32 位”的“任何 CPU”)和 ,我也会遇到这种情况“调试” 模式。

之所以有时会发生这种情况,是因为系统可能会将值保存在具有“额外”精度的 80 位 CPU 注册表中。但是当放入真正的 64 位 Double 时,它会改变值。

如果你变成:

var isZeroA = (double)(a * 0.1) == 0;

然后正式地你真的什么都没有改变(从 doubledouble 的转换!),但实际上这可能会迫使运行时从 80 位转换为64 位。它会改变你的输出吗? 编辑:这个“无操作”转换对我来说改变了一些东西!有关 C# 中浮点类型的此类转换为 self 的技巧的更多信息,请参阅其他线程 Casting a result to float in method returning float changes result .

请注意,由于这些 64 位/80 位问题。查看其他线程 Is floating-point math consistent in C#? Can it be?


以下更简单的程序也显示了存在问题的情况(至少在我的系统上):

double j = 9.88131291682493E-324;
Console.WriteLine(j * 0.1 == 0); // "False"
double k = j * 0.1;
Console.WriteLine(k == 0); // "True"

Console.WriteLine((double)(j * 0.1) == 0); // "True", double-to-double cast!

您甚至可以在该代码中以 j = 1E-323 开头。它导致相同的 Double


引用:经常被引用的文件What Every Computer Scientist Should Know About Floating-Point Arithmetic David Goldberg 以 an added section Differences Among IEEE 754 Implementations 出现在互联网上由一位匿名作者(不是戈德堡)撰写。 IEEE 754 实现之间的差异部分以技术方式解释了您看到的问题。

另见 x86 Extended Precision Format (Wikipedia page section)关于这种 80 位格式。

关于c# - 为什么将值存储在变量中会改变相等比较的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34086393/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com