Операция по модулю на силовой функции - PullRequest
0 голосов
/ 29 января 2020

Я получаю эту ошибку при выполнении операции по модулю для функции питания.

 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;
}

Ответы [ 3 ]

1 голос
/ 29 января 2020

pow возвращает double, по модулю может работать только на int. Добавьте некоторые объясняющие переменные, и это станет более очевидным. Код также будет более читабельным и более производительным.

0 голосов
/ 29 января 2020

Неправильные типы

Сообщение об ошибке компилятора является следствием того факта, что подпрограмма pow имеет тип double, но оператор % принимает только целочисленные операнды.

pow - это заманчивая процедура, используемая для возведения в степень, но она возвращает тип с плавающей запятой, и, как правило, не следует смешивать арифметику с плавающей запятой и целочисленную арифметику c по следующим причинам:

  • Там Существенные проблемы и тонкости в использовании арифметики с плавающей точкой c, включая проблемы с обработкой ошибок округления.
  • Некоторые реализации 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;
}

Таким образом, вместо многократного использования степени 5 (5, 25, 125, ...) с n, вместо этого мы делим n на 5 раз.

Другие проблемы

Эти изменения дадут код, который будет делать то же, что и код в вашем вопросе, если pow вернул целочисленный тип, для случаев где это не будет переполнено. Однако, я подозреваю, что в вашем коде есть другие проблемы, и он не вычисляет то, что вы хотели.

Я думаю, что наиболее вероятно, что ваше назначение было написать программу, которая вычисляет количество конечных нулей в п ! ( n факториал) при десятичной записи. Количество конечных нулей в n ! является показателем величайшей степени 10, которая делит n !. Эта мощность определяется коэффициентами 5, которые доступны, потому что для каждого завершающего нуля требуется коэффициент 2 и коэффициент 5 (чтобы сделать 10) в n !, но он ограничен факторами 5, потому что множителей 2 много.

Таким образом, 1 !, 2 !, 3 !, и 4! не имеют конечных нулей, потому что они не имеют коэффициентов 5. 5! имеет один завершающий ноль, как и 6 !, 7 !, 8 !, и 9 !. Тогда 10! имеет два запаздывающих нуля, как мы видим, поскольку 1 • 2 • 3 • 4 • 5 • 6 • 7 • 8 • 9 • 10 имеет два фактора по 5. Задние нули увеличиваются до трех при 15! и четыре в 20 !. Пока что число конечных нулей составляет n ! n / 5, усеченное до целого числа. Затем в 25 !, мы добавляем не один, а два фактора из 5, поскольку 25 равно 5 2 . Теперь число конечных нулей не n / 5, а n / 5 + n / 5/5. Подумав немного, мы видим, что, как правило, число конечных нулей составляет n ! n / 5 + n / 5/5 + n / 5/5/5 + n / 5/5/5 / 5 +…, заканчивающийся там, где термин достигает нуля.

Если ваша программа продолжалась, в то время как n / 5 j не было нулем вместо когда n по модулю 5 j равняется нулю, он вычисляет эту сумму. Сходство вашей программы с этим расчетом заставляет меня подозревать, что это было намерение. Если это так, измените строки на:

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

(я сформулировал это для простоты, но мы также можем видеть, что, если n <5, последняя итерация l oop ничего не добавляет, поэтому мы также можем изменить условие l oop с <code>0 < n на 5 <= n.)

Кроме того, сумма не сбрасывается при чтении нового n. Удалите объявление sum перед первым for l oop и вставьте int sum = 0; после первого for и перед second.

Как правило, рекомендуется не объявлять вещи, прежде чем они вам нужны. Поэтому удалите объявление n с вершины main и поместите его после первого for. Удалите объявления i и j перед for l oop и определите каждое в его for l oop: for (int i = 0; i < t; i++) и for (int j = 1; 5 <= n; j++).

In cout << sum;, вам, вероятно, нужен символ новой строки: cout << sum << '\n'; или cout << sum << std::endl;.

Не включать <bits/stdc++.h>. Вместо этого, включая стандартные заголовки, такие как <iostream> для этой программы.

Избегайте использования using namespace std;. Используйте std:: в своем коде (, например, , std::cin вместо cin), даже если это требует большего набора текста или выбора при выборе нескольких определенных c вещей из пространств имен, таких как using std::cin; вместо всего пространства имен. Хотя изначально это требует больше работы, оно избегает программ и обучает вас лучше понимать, что использует ваша программа.

0 голосов
/ 29 января 2020

Как упомянуто @Keynan, pow возвращает double, тогда как % требует, чтобы аргумент был int. Чтобы это сработало, вы можете привести результат к int с использованием static_cast или C в стиле.

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

Ссылки по теме:

...