在不同的平台上给出不同的结果

时间:2018-02-09 00:01:03

标签: c++ linux macos

我正在尝试用C ++实现一个系统,我可以判断一个数字是否完整(十进制之后的所有内容都为零)。为此,我使用if (sqrt(answer / 2) == floor(sqrt(answer / 2)))

我的问题是我在不同的系统,macOS和Linux Fedora 27上得到不同的结果。在我的Linux机器上运行GCC 7.3.1 20180130并且macOS机器在我的学校,我无法检查它们马上。我知道macOS使用的是旧版本的开源工具。

我的整个代码是:

#include <iostream>
#include <cmath>
using namespace std;
int main() {
  double answer = 1.0;
  loop:
// uncomment line under for verbose
  cout << "testing " << answer << endl;
  if (sqrt(answer / 2) != floor(sqrt(answer / 2))) {
    answer++;
    goto loop;
  } else { if (cbrt(answer / 3) == floor(cbrt(answer / 3))) {
      cout << "ANSWER IS " << answer << endl;
      return 0;
    } else {
      answer++;
      goto loop;
    }
  }
  return 0;
}

我已经编写了一些I / O对的列表:

cbrt(answer / 3.0) answer648.0时的6输出为floor(cbrt(answer / 3.0))

answer 648.06时的(cbrt(answer / 3.0) == floor(cbrt(answer / 3.0)))输出为(cbrt(648.0 / 3.0) == floor(cbrt(648.0 / 3.0)))

Arrays.asList()是假的

Collection是真的

我知道这可能是一个浮点问题,我不知道是否有更好的方法来检查一个数字是否是整数。

如果我需要澄清任何事情,请告诉我。

2 个答案:

答案 0 :(得分:0)

sqrt()和cbrt()不必进入此阶段。通过&#34;整数&#34;的正常数学定义,您需要知道的是小数部分是否为零。它应该足以检查:

if(floor(answer)== answer)...

你在这里遇到不匹配的原因可能与sqrt()或cbrt()没什么关系。它更多的是除以3.0。在基数10中,当除以3时,会得到一个重复的小数,例如:

1.0 / 3.0 = 0.3333333 ......

浮点数 - 即使是双数 - 也只能保持这么高的精度。即使你将上面的数字乘以3.0,也可能会稍微偏离:

(1.0 / 3.0)* 3.0 = 0.9999999 ......

有些计算机实现&#34;除以3.0&#34; as&#34;乘以三分之一&#34;内部。它们可以在最后一位数字中关闭一个位,但这足以将1.0更改为0.9999 ...这些数字会在你将它们放置时产生不同的结果。

在最后一个数字问题中,sqrt()和cbrt()函数可能有类似的偏差。

避免这种情况的一种方法是说,&#34;嗯,我只想要一些关闭的东西到一个整数。&#34;然后你就可以决定它的接近程度,然后测试一下:

if(abs(round(answer) - answer)&lt; .0001)...

机器算术的这些细节可能很快变得复杂。在不同条件下,不同的机器可能在最后一位数具有不同的答案。除非并且直到你为复杂的东西做好准备,否则像上面那样的东西可能是最好的解决方案。

答案 1 :(得分:0)

可能不同的系统对其浮点值具有不同的精度级别,因此(例如)一个可能最终得到XX.9999997而另一个得到XX.00000020。这是使用ceilfloor的重要原因。相反,如果您需要四舍五入,只需使用round

在这种情况下,您可以使用fabs(浮点绝对值)来确保您处于某个阈值之下:

if(fabs(answer - static_cast<int>(answer)) < THRESHOLD) {
    std::cout << "We're whole!";
}