我在对幂函数执行模运算时遇到此错误。
invalid operands of types ‘int’ and ‘__gnu_cxx::__promote_2<int, int, double, double>::__type {aka double}’ to binary ‘operator%’
这是我的一段代码。
#include <bits/stdc++.h>
using namespace std;
int main() {
int t, n;
cin >> t;
int i, j, sum = 0;
for (i = 0; i < t; i++) {
cin >> n;
for (j = 1; (n % pow(5, j)) == 0; j++)
sum = sum + (n / pow(5, j));
cout << sum;
}
return 0;
}
pow返回一个double,modulo只能对int进行运算。再加上一些解释变量,这一点会变得更加明显。代码也将更具可读性和性能。
错误类型
编译器错误消息是由于pow
例程执行double
类型的例程,但%
运算符只接受整数操作数。
pow
是一个很有吸引力的求幂例程,但它返回浮点类型,通常不应该混合使用浮点和整数运算,原因包括:
- 使用浮点运算有相当多的问题和微妙之处,包括处理舍入错误的问题
pow
的一些实现的不足之处在于,当精确答案在double
类型中表示时,它们返回不精确的答案。例如,pow(5, 3)
可能返回一个略低于125的数字,然后取一个余数取模(或将其截断为整数)将不会得到您想要的结果
更好的方法
解决当前问题的一种方法是用自己的例程替换pow
,该例程只需重复相乘即可将整数提升为非负整数幂。然而,还有更好的方法。更改这两行:
for (j = 1; (n % pow(5, j)) == 0; j++)
sum = sum + (n / pow(5, j));
到此:
for (j = 1; n % 5 == 0; j++)
{
n /= 5;
sum = sum + n;
}
因此,我们不是对n
重复使用5(5,25125,…)的幂,而是将n
重复除以5。
其他问题
如果pow
返回整数类型,则这些更改将为代码提供问题中的代码所做的操作(在不会溢出的情况下)。然而,我怀疑您的代码中还有其他问题,并且它没有计算出您想要的内容。
我认为你的任务很可能是编写一个程序,计算n中的尾随零的数量!(n阶乘)。n中的尾随零的数目!是10的最大幂除以n!的指数!。这个功率是由可用的因子5决定的,因为在n!中,每个尾随零都需要因子2和因子5(即10)!,但是它受到因子5的约束,因为因子2是充足的。
因此,1!,2.3.和4!没有尾随零,因为它们没有因子5。5.有一个尾随零,6也是!,7.8.和9!。然后是10!有两个尾随零,正如我们所看到的,因为1•2•3•4•5•6•7•8•9•10有两个因子5。后面的0在15时增加到3!20岁时有四个!。到目前为止,n的尾随零的数量!是n/5,截断为整数。然后,在25岁的时候!,我们不是加一个而是加两个因子5,因为25是52。现在,尾随零的数量不是n/5,而是n/5+n/5/5。经过一些思考,我们可以看到,通常,n的尾随零的数量!是n/5+n%5%5+n/5/5/5+n/5/5/5/5+…,在项达到零时结束。
如果您的程序在n/5j不为零时继续,而不是在n模5j为零时,它将计算此和。你的程序与这个计算的相似性让我怀疑这就是目的。如果是,请将行更改为:
for (j = 1; 0 < n; j++)
{
n /= 5;
sum = sum + n;
}
(为了简单起见,我是这样表述的,但我们也可以看到,如果n<5,则循环的最后一次迭代不添加任何内容,因此我们也可以将循环条件从0 < n
更改为5 <= n
。)
此外,当读取新的n
时,总和不被重置。删除第一个for
循环之前的sum
声明,并在第一个for
之后和second
之前插入int sum = 0;
。
一般来说,在你需要东西之前不要申报是一种很好的做法。因此,从main
的顶部移除n
的声明,并将其放在第一个for
之后。在for
循环之前删除i
和j
的声明,并在其for
循环中定义每一个声明:for (int i = 0; i < t; i++)
和for (int j = 1; 5 <= n; j++)
。
在cout << sum;
中,您可能需要一个新行字符:cout << sum << 'n';
或cout << sum << std::endl;
。
不包括<bits/stdc++.h>
。相反,包括标准标头,例如此程序的<iostream>
。
避免使用using namespace std;
。在代码中使用std::
(,例如,std::cin
而不是cin
),即使它需要更多的类型或选择性地从命名空间中提取一些特定的东西,例如using std::cin;
而不是整个命名空间。虽然这最初需要更多的工作,但它避免了程序,并训练您更好地了解程序正在使用的内容。
如@Keynan所述,pow
返回一个double
,而%
要求参数为int
。要使其工作,可以使用static_cast
或C样式强制转换将结果强制转换为int
。
// static_cast
for (j = 1; (n % static_cast<int>(pow(5, j))) == 0; j++)
// c-style cast
for (j = 1; (n % (int)pow(5, j)) == 0; j++)
相关链接:
- 为什么
int pow(int base, int exponent)
不在标准C++库中