项目欧拉挑战3

时间:2013-11-06 01:59:04

标签: c

我的代码出了问题,我不知道是什么。 GCC在没有任何警告的情况下编译它,但在运行时没有输出任何内容。

我只是在学习c(这实际上是欧拉的问题3。找到最大的素数因子600851475143)。

这段代码出了什么问题?

#include <stdio.h>

int primeCheck(unsigned long input);

int main(){
  //goal: find largest prime factor of 600851475143
  unsigned long goal = 600851475143;
  for(unsigned long i = 600851475142; i > 0; i--){
    if(primeCheck(i) == 1 && goal%i == 0)
      printf("\n%lu\n\n", i);
  }

}

int primeCheck(unsigned long input){
  for(unsigned long i = 2; i < input; i++){
    if(input%i == 0)
      return 0;
  }
  return 1;
}

3 个答案:

答案 0 :(得分:0)

你的程序最有可能太长来执行。尝试较小的数字,杰瑞暗示验证你的程序。

您可能需要查看此帖子: Prime factorization for big numbers 以获得更好的算法。

答案 1 :(得分:0)

假设您正在使用正确大小的数据结构(已经有足够的讨论),您的程序肯定执行时间太长。

请注意,除非6​​00851475143本身是素数,否则最大素数因子不能超过1/3(我们可以清楚地看到2当然不是一个因素)。这说的是,几乎没有数学,我已经可以告诉你,第一个for循环中的if语句将返回false超过4000亿次,并且你正在对每个语句进行素数检查 即可。我不在乎你使用什么算法;你不能快速进行4000亿的素性检查。即使你换掉它来利用短路,你也要进行4000亿次的可分性检查,这也是无效的。

由于这个 Project Euler,我不会放弃它,但我会给出一个提示:假设你知道一些较小的素因子。您如何使用它来设置最大因子有多大的上限?

答案 2 :(得分:0)

OP的代码适用于64位unsigned long,但需要很长时间。

问题:

primeCheck()最多迭代i < input而不是i <= isqrt(input)。两者都可以工作,但只需要达到input的平方根,代码就可以更快地完成 。不需要进一步测试。

通常,余数和商一起计算,因此通过对商进行测试,代码可以免费获得“关于平方根” - 除数何时变得小于商?

int primeCheck(unsigned long input){
  unsigned long q = input;
  // for(unsigned long i = 2; i < input; i++){
  for(unsigned long i = 2; i <= q; i++){
    if(input%i == 0) {
      return 0;
    }
    q = input/i;
  }
  return 1;
}

主循环开始寻找比目标少1的因子。这将有效,但第一个可能的因素是isqrt(goal)。这要快得多

int main() {
  //goal: find largest prime factor of 600851475143
  unsigned long long goal = 600851475143;
  unsigned long goal_sqroot = (unsigned long) sqrt(goal);

  // In case  `double sqrt(double)` gave a too low `isqrt()` answer ...
  if (goal/goal_sqroot > goal_sqroot) goal_sqroot = goal/goal_sqroot;

  // for(unsigned long i = 600851475142; i > 0; i--){
  for (unsigned long long i = goal_sqroot; i > 1; i--) {
    if (primeCheck(i) == 1 && goal % i == 0)
      printf("%llu\n", i);
  }
}

unsigned long可能只是32位。使用unsigned long long获取更大的数字,例如600851475143,一个40位数字。

输出&lt; 2秒:

6857
1471
839
71

其他简化可能,这是一个开始。