Stefan_Lang
Прежде всего, есть ряд проблем с вашим вопросом. Вы могли бы избежать большинства из них, просто прочитав и следуя советам, предложенным при вводе вашего вопроса здесь! Не делая этого, вы усложняете задачу для тех, кто готов помочь, и, как следствие, вероятность того, что кто-то ответит полезным ответом, значительно меньше.
Кроме того, сделать это проще для людей, которые пытаются Вам помочь, - это вопрос уважения. Если вы просто сбросите свой код здесь, это будет неуважительно по отношению к тем, кто должен вам помочь! Пожалуйста, приложите больше усилий в следующий раз, когда будете задавать вопрос.
Во-вторых, когда вы публикуете вопрос, добавьте его в свой код! Мы не можем читать ваши мысли, не видим ни вашего экрана, ни оригинального описания задачи, над которой вы работаете! Опишите результат, который вы получаете, и результат, который вы ожидаете, а также любые сообщения об ошибках, которые вы видите. Любая часть этой информации, которую вы опустите, просто оставит нас в неведении и, скорее всего, приведет к предложениям, которые вам не помогут.
Third, when you write code, do yourself and everyone else a favor and use names that are self-explanatory! "getResult" or "a" aren't useful at all! Use names that offer an insight about what they are used for, e. g. "sumOfDivisors". In case of "a", "sum_of_divisors" would also be a fitting name, but since that is exactly what the function does, you could simply name it "result", implying that this is the variable to store the sum of divisors. You did use "sum" and "final_sum" in your main function, but in this case the prefix "final" doesn't help in clarifying the difference between the two, as you are summing totally different numbers! "sum" should be "sum_of_divisors" and "final_sum" should be "sum_of_good_numbers" - that would instantly clarify what you are storing and calculating here!
Наконец, для производительности попробуйте следующие вещи:
1. Научиться использовать профилировщик. Вы, конечно, можете попытаться сделать обоснованное предположение, какие части вашего кода занимают больше всего времени, но даже очень опытные программисты, как правило, испытывают сюрпризы, когда фактический профилировщик говорит им, где искать. Основная причина этого заключается в том, что современные компиляторы обычно гораздо лучше распознают и оптимизируют неэффективные сегменты кода, чем сами программисты, а узкие места производительности, которые остаются после оптимизации компилятора, гораздо труднее обнаружить.
2. Первое, на что нужно обратить внимание, когда у вас возникают проблемы с производительностью, - это избыточный код, а это означает, в первую очередь, код внутри циклов, поскольку это код, который выполняется повторно. Проверьте, содержит ли код цикла какие-либо операторы, которые могут быть перемещены за пределы цикла. Вычисление их один раз, перед началом цикла избавляет вас от ненужных повторений одних и тех же вычислений. Обратите внимание, что любые вычисления, выполняемые в операторе for (или условия в циклах do и while), являются частью этого кода цикла!
Пример:
- ваше сравнение i<=sqrt(n) выполняется для каждой итерации. Вы можете переместить вычисление, вызванное в этом сравнении, из цикла.
- вы можете вычислить n/i только один раз и сохранить его во вспомогательной переменной или настроить свой код, чтобы вам не нужно было пересчитывать его несколько раз.
3. проверьте, содержит ли ваш код цикла нетривиальные вычисления или вызовы функций. Подумайте о замене их чем-то более эффективным.
Например, когда вы делаете сравнение, включающее такие вещи, как квадратные корни или деления, попробуйте переформулировать их таким образом, чтобы они использовали вместо этого умножения. например, вместо i<=sqrt(n) вы могли бы написать i*i<=n. Конечно, в этом случае, если вы переместите вычисление sqrt за пределы цикла, это будет всего один sqrt, но если вы реформируете сравнение с помощью i*i, то у вас будет много умножений, которые в этом случае не могут быть улучшением! Так что будьте осторожны, где использовать эту идею.
4. вызовы функций занимают значительно больше времени, чем простые операции, такие как * или /. Когда у вас есть вызов функции внутри цикла, проверьте, помогает ли объявление его встроенным.
Пример: ваша основная функция вызывает getResult() в цикле. Попробуйте объявить getResult() как встроенный.
5. когда у вас есть цикл, подумайте о способах повторного использования результатов предыдущих итераций, чтобы помочь вычислить результаты для последующих итераций.
Пример: для каждого четного числа n=2*k делители k также являются делителями n. Предупреждение: это не тривиально, чтобы найти все дополнительные делители, и это требует хранения делителей предыдущих чисел - это может потребовать большого объема памяти, и просто поддерживать эту память может стоить больше производительности, чем вы могли бы получить. Однако, если вы подумаете в соответствии с первоначальной идеей, вы можете придумать совершенно другой алгоритм:
Вместо того чтобы находить все делители всех чисел до n, постройте все "хорошие" числа n, комбинируя делители! Для этой идеи полезно было бы услышать о "Геделевская нумерация[^]" В основном это кодировка, которая представляет данное число n его простыми множителями. например, число 12 имеет код Геделя {"2","1"}, потому что 12=2^2*3^1, и 15 имеет код Геделя {"0","1","1"} потому что 15=2^0*3^1*5^1.
Хорошая вещь о представлениях Геделя заключается в том, что вычисление суммы делителей намного проще. Плохо то, что, хотя вы можете перечислять (или упорядочивать) числа, используя их коды Геделя, этот порядок не соответствует естественному порядку фактических чисел. Поэтому это немного сложно, чтобы перечислить "все числа до n"
Я не буду описывать (довольно сложные) шаги по реализации этого решения, так как не думаю, что автор этой задачи действительно стремился к такому решению. Вместо этого я собираюсь предложить.
6. Используйте распараллеливание для повышения производительности. Как и 5, это может быть не то, к чему стремился автор задачи. Но если он это сделал, просто используйте несколько потоков для вызова getResult() для разных номеров в вашем основном цикле.