【问题标题】:How to reproduce floating point cos(x)!=cos(x)如何重现浮点 cos(x)!=cos(x)
【发布时间】:2015-06-11 16:30:15
【问题描述】:

如何重现这种行为? https://isocpp.org/wiki/faq/newbie#floating-point-arith2

准确来说,在下面的代码中,参数xy是相等的;它们可以等于 1.0 或任何其他值。

void foo(double x, double y)
{
  double cos_x = cos(x);
  double cos_y = cos(y);
  // the behavior might depend on what's in here
  if (cos_x != cos_y) {
    std::cout << "Huh?!?\n";  // You might end up here when x == y!!
  }
}

一些编译器选项?环形?有什么想法吗?

【问题讨论】:

  • 你不能。这完全取决于您的配置,会发生什么。这就是为什么会有评论// You might end up here when x == y!!
  • 尝试一个高精度(读作:非常长)的数字,您可以输入许多小数位,看看会发生什么。
  • 你需要一个旧版本的 C 编译器,它仍然生成具有可怕的 80 位内部格式的 FPU 代码,并且有足够的精力来修补代码以便优化器破坏它。那是你生命中永远不会回来的一周。关键是,这可能会发生,而您无需寻找它。
  • 我认为这不会像文章所说的那样发生。它可能发生,但可能性不大
  • @HansPassant 所以使用新的编译器理论上不会发生这种情况?即使有一些编译器选项?

标签: c++ c floating-point-precision x87


【解决方案1】:

我会尝试按照链接示例中的方式进行操作:不将结果存储到临时变量中。文章提到浮点运算通常在比 RAM 具有更多位的寄存器中计算。例如,如果只有一个浮点运算寄存器,那么在进行cos 计算之后,结果必须存储在 RAM 中,以便进行另一个cos 计算。来自文章:

假设您的代码计算 cos(x),然后截断该结果并将其存储到一个临时变量中,例如 tmp。然后它可能会计算 cos(y),并且(请打鼓)将 cos(y) 的未截断结果与 tmp 进行比较,即与 cos(x) 的截断结果进行比较。

当您将两个结果都存储在变量中(取决于优化等)时,第二个cos 计算的结果很有可能在计算之前也将存储在 RAM 中。由于结果将以相同的方式截断,因此它们将比较为==

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-10
    • 2020-02-16
    • 2023-01-14
    • 1970-01-01
    • 2020-03-01
    • 2015-04-30
    • 2016-04-19
    • 1970-01-01
    相关资源
    最近更新 更多