-1

I am getting this error while performing modulo operation on power function.

 invalid operands of types ‘int’ and ‘__gnu_cxx::__promote_2<int, int, double, double>::__type {aka double}’ to binary ‘operator%’

this is my piece of code.

#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;
}
Zheng Qu
  • 587
  • 5
  • 17
  • Please declare your variables – Keynan Jan 29 '20 at 07:23
  • Does this answer your question? [C++ function returning wrong data type](https://stackoverflow.com/questions/42145909/c-function-returning-wrong-data-type) – Raymond Chen Jan 29 '20 at 07:24
  • Does this answer your question? [invalid operands of types \`double' and \`int' to binary \`operator%'](https://stackoverflow.com/questions/38024995/invalid-operands-of-types-double-and-int-to-binary-operator) – walnut Jan 29 '20 at 08:01
  • 1
    Note that in such a situation, it is more efficient to calculate *powers of 5* iteratively; `pow5 = 5 * pow5;` – Damien Jan 29 '20 at 08:11
  • 1
    What is this code supposed to accomplish? I suspect that you should also move `sum = 0` inside the loop and add a `<< '\n'` to `cout << sum`. Besides, you may want to look at https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h and https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice – Bob__ Jan 29 '20 at 09:07

3 Answers3

1

pow is returning a double, modulo can only operate on int. Throw in some explaining variables and this will become more obvious. The code will also be more readable and more performant.

Keynan
  • 1,318
  • 1
  • 10
  • 17
0

Like @Keynan mentioned, pow returns a double while % requires the argument to be int. To make it work, you can cast the result to int with either static_cast or C-style cast.

// 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++)

Related links:

Zheng Qu
  • 587
  • 5
  • 17
  • The type does not have to be `int`. It just has to be any integral/enumeration type. Also casting the result of `pow` to `int` is not good advice. The result may not be exactly representable in `double` and `pow` may accumulate error, so the result may differ from the mathematically expected result. – walnut Jan 29 '20 at 08:06
  • 1
    Implicit conversions are not considered (`double` would be implicitly convertible to `int`). See https://timsong-cpp.github.io/cppwp/n4659/expr.mul#2. I would write an integer `pow` (see https://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int) or in this particular case don't use `pow` at all. The multiplicity of `5` in `n`'s prime factorization can be calculated by simple repeated division/modulo by `5`. – walnut Jan 29 '20 at 08:30
  • Converting the `pow` result to `int` is not a good solution. The use of `pow` is wasteful and problematic (including because there are poor implementations that return inexact results when exact results are possible, sometimes resulting in conversion to `int` producing a lower result than desired). Instead, this code should be changed to use simple integer multiplications or divisions, not `pow`. – Eric Postpischil Jan 29 '20 at 09:58
  • @EricPostpischil I see your point. But even with simple integer multiplications you still have to check whether the result overflows `int`, right? – Zheng Qu Jan 29 '20 at 10:26
  • @Maverobot: No, not when the code is correctly written. Instead of using an increasing power of 5, one can repeatedly divide `n` by 5, and then there will be no overflow. – Eric Postpischil Jan 29 '20 at 12:39
0

Wrong Types

The compiler error message results from the fact that the pow routine routines a double type, but the % operator accepts only integer operands.

pow is a tempting routine to use for exponentiation, but it returns a floating-point type, and you generally should not mix floating-point and integer arithmetic, for reasons including:

  • There are considerable problems and subtleties in using floating-point arithmetic, including issues with handling rounding errors.
  • Some implementations of pow are deficient in that they return inexact answers when exact answers are representable in the double type. For example, pow(5, 3) might return a number slightly below 125, and then taking a remainder modulo that (or its truncation to an integer) would not give the result you want.

Better Method

One way to resolve the immediate problem is to replace pow with a routine of your own that raises an integer to a non-negative integer power simply by multiplying repeatedly. However, there is a better approach. Change these two lines:

for (j = 1; (n % pow(5, j)) == 0; j++)
    sum = sum + (n / pow(5, j));

to this:

for (j = 1; n % 5 == 0; j++)
{
    n /= 5;
    sum = sum + n;
}

So, instead of repeatedly using a power of 5 (5, 25, 125,…) with n, we instead divide n by 5 repeatedly.

Other Issues

These changes will give code that does what the code in your question would do if pow returned an integer type, for cases where it would not overflow. However, I suspect there are other issues in your code and it does not compute what you intended.

I think it is most likely your assignment was to write a program that computes the number of trailing zeros in n! (n factorial) when written in decimal. The number of trailing zeros in n! is the exponent of the greatest power of 10 that divides n!. This power is determined by the factors of 5 that are available, because every trailing zero requires a factor of 2 and a factor of 5 (to make 10) in n!, but it is constrained by the factors of 5 because factors of 2 are plentiful.

Thus, 1!, 2!, 3!, and 4! have no trailing zeros because they have no factors of 5. 5! has one trailing zero, and so do 6!, 7!, 8!, and 9!. Then 10! has two trailing zeros, as we can see since 1•2•3•4•5•6•7•8•9•10 has two factors of 5. The trailing zeros increase to three at 15! and four at 20!. So far, the number of trailing zeros of n! is n/5, truncated to an integer. Then, at 25!, we add not one but two factors of 5, since 25 is 52. Now the number of trailing zeros is not n/5 but n/5 + n/5/5. With some thought, we can see that, in general, the number of trailing zeros of n! is n/5 + n/5/5 + n/5/5/5 + n/5/5/5/5 + …, ending where the term reaches zero.

If your program continued while n / 5j was not zero instead of when n modulo 5j was zero, it would calculate this sum. The similarity of your program to this calculation leads me to suspect that was the intent. If so, change the lines to:

for (j = 1; 0 < n; j++)
{
    n /= 5;
    sum = sum + n;
}

(I have phrased it this way for simplicity, but we can also see that, if n < 5, the final iteration of the loop adds nothing, so we can also change the loop condition from 0 < n to 5 <= n.)

Additionally, the sum is not reset when a new n is read. Remove the declaration of sum before the first for loop and insert int sum = 0; after the first for and before the second.

Generally, it is good practice not to declare things before you need them. So remove the declaration of n from the top of main and put it after the first for. Remove the declarations of i and j before the for loop and define each one in its for loop: for (int i = 0; i < t; i++) and for (int j = 1; 5 <= n; j++).

In cout << sum;, you probably want a new-line character: cout << sum << '\n'; or cout << sum << std::endl;.

Do not include <bits/stdc++.h>. Instead, including standard headers, such as <iostream> for this program.

Avoid using using namespace std;. Use std:: in your code (e.g., std::cin instead of cin) even though it requires more typing or be selective about taking a few specific things from namespaces, such as using std::cin; instead of the entire namespace. While this initially requires more work, it avoids programs and trains you to be better cognizant of what your program is using.

Community
  • 1
  • 1
Eric Postpischil
  • 141,624
  • 10
  • 138
  • 247
  • Thanks a lot for your answer ,and i loved the you guessed the question i was stuck in and then helping me out getting my first successful submission. Also this was my first question in Stack ,and the kind of response i had, i'm now in love with this community. Thanks a lot. – Nishant kumar Jan 29 '20 at 19:16