我正在制作一个个人项目,我需要确定0到999之间的所有prime powers。因为我不是特别擅长数学,所以我厌倦了以下火腿蛮力的暴力方法。
bool constexpr is_prime(int imp)
{
return imp == 1 ? false : (imp % imp == 0 && imp % 1 == 0 && [&imp]{ for(int i = 2; i < imp; ++i) if(imp % i == 0) return false; return true;}());
}
bool is_prime_power(int imp)
{
for(int i = 1; i < 1000; ++i)
if (is_prime(i))
for (int j = 0; j < 100; ++j)
if (imp == pow(i, j))
return true;
return false;
}
对于0 ... 30,输出应该是(根据A000961):
1 2 3 4 5 7 8 9 11 13 16 17 19
然而,这就是我所得到的:
1 2 3 4 5 7 8 9 11 16 19
13和17哪里消失了?
由于我的方法无法找到任何逻辑问题,因此我实现了自己的pow()函数。
double constexpr _pow(double base, double exp)
{
return exp == 0 ? 1 : base*pow(base, exp - 1);
}
现在,如果我从math.h调用我的_pow()而不是pow(),则输出显示为例外。我的实施错了吗?如果没有,math.h中的pow()无法正常工作。 知道是什么导致了这个吗?
答案 0 :(得分:3)
问题是double
(和一般的浮点数)不准确,标准库中的数学函数也使用近似公式进行计算。如果您致电pow(2, 10)
,您可能会获得1023.999375
(根据具体情况,可能会被截断为1023
)。
因此,不是使用标准库中的浮点pow()
函数,而是可以使用自己的完全实现整数:
int constexpr _pow(int base, int exp)
{
return exp == 0 ? 1 : base * _pow(base, exp - 1);
}
(或者如果您需要unsigned
或long long
,请将其更改为您想要的任何整数类型。
答案 1 :(得分:1)
您永远不需要验证一个数字是否分开,而一个数字除以一个数字。这没用:imp % imp == 0 && imp % 1 == 0
否则你遇到的问题是因为pow会在将它与整数进行比较时返回double或float。由于舍入误差,comaparison可能会失败。我建议你实现自己的整数幂操作,以避免任何舍入错误。或者将i转换为double并使用与一些小epsylon容差的比较。