我从之前关于此主题的主题中了解到,使用float算法会导致精度异常。但有趣的是我观察到相同的函数表现为两种不同的方式。
使用COUT输出 4 但如果我将结果保存到变量中,则结果 3 < / b>!
#include <iostream>
#include <cmath>
using namespace std;
#define mod 1000000007
long long int fastPower(long long int a, int n){
long long int res = 1;
while (n) {
if (n & 1) res = (res * a) % mod;
n >>= 1; a = (a * a) % mod;
}
return res;
}
int main() {
int j = 3;
cout << pow(64, (double)1.0/(double)j) << endl; // Outputs 4
int root = pow(64, (double)1.0/(double)j);
cout << root << endl; // Outputs 3
/* As said by "pts", i tried including this condition in my code but including this line in my code resulted in TimeLimitExceeded(TLE). */
if (fastPower(root+1,j) <= 64) root++;
cout << root << endl; // Outputs 4 :)
return 0;
}
Code output on Ideone.com
现在,我们如何在编程竞赛中避免此类错误。
我不想使用'round'函数,因为我只需要root的整数值。即
63 (1/6) = 1,20 (1/2) = 4等...
我应该如何修改我的代码,以便将正确的结果存储在根变量中。
答案 0 :(得分:2)
据我所知,C和C ++中没有单行答案可以使a
的{{1}}根被舍入。
作为一种快速解决方法,您可以执行以下操作:
b
这不适用于每个值,但通过调整常量(int root(int a, int b) {
return floor(pow(b, 1.0 / a) + 0.001);
}
),您可能会很幸运,它可以用于测试输入。
要解决此问题,请在使用0.001
时使用pow
,如果它返回r
,请通过乘法尝试r - 1
,r
和r + 1
它返回(使用整数的快速取幂)。这大部分时间都可以使用。
如果您需要一种可以100%工作的解决方案,那么请不要使用浮点数。例如,使用指数二进制搜索。有更快的算法(如牛顿迭代),但如果你在整数上使用它们,那么你需要编写自定义逻辑,以便在它们停止收敛时找到确切的解决方案。
答案 1 :(得分:2)
pow返回双倍。当使用cout时,它是圆形的(因此,它是4)。当你将它转换为int时,它只是截断小数部分。 Pow返回类似4-eps的东西(由于精度问题)。当它被截断时,它等于3。
肮脏的黑客在编程竞赛中很有用:int root = (int)(pow(...) + 1e-7)
答案 2 :(得分:0)
您的计划有两个问题:
pow(int, int)
重载不再可用。要避免此问题,请将第一个参数转换为double
,float
或long double
。
此外,cout
的命令正在上层回答您的答案(3.something into 4)并保存您的数据正在删除所有小数部分并且仅接受整数部分。