证明存在三个浮点数,使得加法的关联属性为假



我正在寻找三个浮点值,这样,(A + B) + C != A + (B + C)

浮点值在 0.002 和 10 的范围内,显然这个问题有很多解决方案。我使用以下算法在 C# 中测试 0.001 到 10.000 的所有值;我在 12 分钟前开始测试,它仍在运行。

for (float i = 0.002f; i < 10f; i = i + 0.001f)
{
    for (float j = 0.002f; j < 10f; j = j + 0.001f)
    {
        for (float k = 0.002f; k < 10f; k = k + 0.001f)
        {
            float FirstAnswer = (i + j) + k;
            float SecondAnswer = (j + k) + i;
            if (FirstAnswer != SecondAnswer)
            {
                Console.Write("(" + i.ToString() + " + " + j.ToString() + ") + " + k.ToString() + " = " + FirstAnswer.ToString() + "n");
                Console.Write("(" + j.ToString() + " + " + k.ToString() + ") + " + i.ToString() + " = " + SecondAnswer.ToString() + "nn");
            }    
        }
    }
}

如您所见,我确保所有值始终是浮动的。我想浮点加法的工作方式必须与常规十进制加法不同,但我看不到连接。有没有更好的算法通过查找给定范围内的所有值来使用浮点值证明加法的关联属性 false?

如果你想生成比较的所有变体并检查女巫场景实际上是失败的,而不使用 EPSILON 进行结果比较,你可以使用 NUnit 框架和 RangeAttribute:

[Test]
public void TestFloatAddition([Range(0.002f,10f,0.001f] float a,
           [Range(0.002f,10f,0.001f] float b, 
           [Range(0.002f,10f,0.001f] float c)
{
    Assert.AreEquals((a + b) + c, a + (b + c));
}

此代码将为每个abc生成测试,您可以在一个会话中运行它。

调试版本和发布版本之间存在差异。如果我运行您的程序的调试版本,则不会得到任何输出。

如果我运行发布版本,我会得到很多输出。

如果按如下方式更改程序,即使在调试版本中也会获得一些输出。我只是在单独的步骤中计算值,如您所见:

for (float i = 0.002f; i < 10f; i = i + 0.001f)
{
    for (float j = 0.002f; j < 10f; j = j + 0.001f)
    {
        for (float k = 0.002f; k < 10f; k = k + 0.001f)
        {
            float FirstAnswer = (i + j);
            FirstAnswer += k;
            float SecondAnswer = (j + k);
            SecondAnswer += i;
            if (FirstAnswer != SecondAnswer)
            {
                Console.Write("(" + i.ToString() + " + " + j.ToString() + ") + " + k.ToString() + " = " + FirstAnswer.ToString() + "n");
                Console.Write("(" + j.ToString() + " + " + k.ToString() + ") + " + i.ToString() + " = " + SecondAnswer.ToString() + "nn");
            }
        }
    }
}

最新更新