使用 mod 和 pow 计算大数
Calculating big numbers with mod and pow
我试图使用以下代码解决 mod 这个大问题。
#include<iostream>
#include<cmath>
using namespace std;
typedef long int li;
li m;
li mod(li b,li p)
{
if(p==0)
return 1;
if(p%2==0)
{
return ((mod(b,p/2)%m)*mod(b,p/2)%m)%m;
//return (li)pow(mod(b,p/2)%m,2)%m;
}
return (b%m*mod(b,p-1)%m)%m;
}
main()
{
li b,p;
while(cin>>b>>p>>m)
{
cout<<mod(b,p)<<endl;
}
}
但它为 ((mod(b,p/2)%m)*mod(b,p/2)%m)%m 提供了不同的输出和 pow(mod(b,p/2)%m,2)%m.i 想知道它们是否相同,如果是,为什么给出不同的输出。
示例输入:
3个
18132
17
17
1765
3
2374859
3029382
36123
没有pow函数的输出:
13
2个
13195
使用 pow 函数输出:
1个
2个
31329
带有pow函数的测试代码
#include<iostream>
#include<cmath>
using namespace std;
typedef long int li;
li m;
li mod(li b,li p)
{
if(p==0)
return 1;
if(p%2==0)
{
//return ((mod(b,p/2)%m)*mod(b,p/2)%m)%m;
return (li)pow(mod(b,p/2)%m,2)%m;
}
return (b%m*mod(b,p-1)%m)%m;
}
main()
{
li b,p;
while(cin>>b>>p>>m)
{
cout<<mod(b,p)<<endl;
}
}
您报告的答案 "without pow function" 是正确的答案,我认为您的代码没问题。所以我认为 您的问题出在您正在应用的测试中,而不是在您的 mod 平方指数函数中。
pow
函数对(双精度)浮点数进行运算,即使两个输入都是小整数,也不能保证给出准确的结果。你正在发生的事情是,在某个时候 pow
返回一个比整数小一点点的值,然后你将它转换为 long int
并得到一个比你小 1 的值 "should",之后一切都错了。
例如,如果您使用您的代码计算 3^6 mod 17,那么在某一时刻它会得到 3^3 mod 17 = 10(到目前为止还可以),然后计算 pow (10,2) ... 而且,至少在我的编译器机器上,结果略小于 100。因此转换为 li
会产生 99 而不是 100,然后我们'死了。
我试图通过检测您的代码以输出中间值来更详细地验证这一点,但有趣的是,由于浮点运算的微妙之处,这通常会失败。 (在变量中保存中间值可能会导致它进行额外的浮点舍入,从而将小于整数的值变成精确的整数值。)
我试图使用以下代码解决 mod 这个大问题。
#include<iostream>
#include<cmath>
using namespace std;
typedef long int li;
li m;
li mod(li b,li p)
{
if(p==0)
return 1;
if(p%2==0)
{
return ((mod(b,p/2)%m)*mod(b,p/2)%m)%m;
//return (li)pow(mod(b,p/2)%m,2)%m;
}
return (b%m*mod(b,p-1)%m)%m;
}
main()
{
li b,p;
while(cin>>b>>p>>m)
{
cout<<mod(b,p)<<endl;
}
}
但它为 ((mod(b,p/2)%m)*mod(b,p/2)%m)%m 提供了不同的输出和 pow(mod(b,p/2)%m,2)%m.i 想知道它们是否相同,如果是,为什么给出不同的输出。
示例输入: 3个 18132 17
17 1765 3
2374859 3029382 36123
没有pow函数的输出: 13 2个 13195
使用 pow 函数输出: 1个 2个 31329
带有pow函数的测试代码
#include<iostream>
#include<cmath>
using namespace std;
typedef long int li;
li m;
li mod(li b,li p)
{
if(p==0)
return 1;
if(p%2==0)
{
//return ((mod(b,p/2)%m)*mod(b,p/2)%m)%m;
return (li)pow(mod(b,p/2)%m,2)%m;
}
return (b%m*mod(b,p-1)%m)%m;
}
main()
{
li b,p;
while(cin>>b>>p>>m)
{
cout<<mod(b,p)<<endl;
}
}
您报告的答案 "without pow function" 是正确的答案,我认为您的代码没问题。所以我认为 您的问题出在您正在应用的测试中,而不是在您的 mod 平方指数函数中。
pow
函数对(双精度)浮点数进行运算,即使两个输入都是小整数,也不能保证给出准确的结果。你正在发生的事情是,在某个时候 pow
返回一个比整数小一点点的值,然后你将它转换为 long int
并得到一个比你小 1 的值 "should",之后一切都错了。
例如,如果您使用您的代码计算 3^6 mod 17,那么在某一时刻它会得到 3^3 mod 17 = 10(到目前为止还可以),然后计算 pow (10,2) ... 而且,至少在我的编译器机器上,结果略小于 100。因此转换为 li
会产生 99 而不是 100,然后我们'死了。
我试图通过检测您的代码以输出中间值来更详细地验证这一点,但有趣的是,由于浮点运算的微妙之处,这通常会失败。 (在变量中保存中间值可能会导致它进行额外的浮点舍入,从而将小于整数的值变成精确的整数值。)