我正在尝试用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)
answer
为648.0
时的6
输出为floor(cbrt(answer / 3.0))
answer
648.0
为6
时的(cbrt(answer / 3.0) == floor(cbrt(answer / 3.0)))
输出为(cbrt(648.0 / 3.0) == floor(cbrt(648.0 / 3.0)))
Arrays.asList()
是假的
Collection
是真的
我知道这可能是一个浮点问题,我不知道是否有更好的方法来检查一个数字是否是整数。
如果我需要澄清任何事情,请告诉我。
答案 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
。这是不使用ceil
或floor
的重要原因。相反,如果您需要四舍五入,只需使用round
。
在这种情况下,您可以使用fabs
(浮点绝对值)来确保您处于某个阈值之下:
if(fabs(answer - static_cast<int>(answer)) < THRESHOLD) {
std::cout << "We're whole!";
}