我有一系列随机数。范围实际上由用户确定,但最多为1000个整数。他们被置于:

vector<int> n

并按以下方式插入值:

srand(1);

for (i = 0; i < n; i++)
  v[i] = rand() % n;

我正在创建一个单独的函数来查找所有非素数值。这就是我现在所拥有的,但我知道这是完全错误的,因为我在系列中得到了素数和复合数。

void sieve(vector<int> v, int n)
{
  int i,j;

  for(i = 2; i <= n; i++)
     {
        cout << i << " % ";
        for(j = 0; j <= n; j++)
           {
              if(i % v[j] == 0)
                 cout << v[j] << endl;
           }
     }
}

当我只有一系列0-1000的数字时,这种方法通常有用,但是当我的数字乱序并且重复时,它似乎不起作用。有没有更好的方法在向量中找到非素数?我很想创建另一个向量,用n个数字填充它,然后找到那些非素数,但效率是否低?

好的,因为范围是0-1000,我想知道是否更容易创建0-n排序的矢量,然后使用筛子找到素数,这是否更接近?

void sieve(vector<int> v, BST<int> t, int n)
{
  vector<int> v_nonPrime(n);
  int i,j;
  for(i = 2; i < n; i++)
      v_nonPrime[i] = i;

  for(i = 2; i < n; i++)
     {

        for(j = i + 1; j < n; j++)
           {
              if(v_nonPrime[i] % j == 0)
                 cout << v_nonPrime[i] << endl;
           }
     }
}
有帮助吗?

解决方案

在此代码中:

if(i % v[j] == 0)
  cout << v[j] << endl;

您正在测试索引以查看它是否可被v [j]整除。我认为你的意思是反过来,即:

if(v[j] % i == 0)

现在,你正在打印i的随机除数。您不打印已知不是素数的随机数。此外,您的输出中将有重复项,也许这没关系。

其他提示

首先,我认为Knuth首先说:过早优化是造成许多错误的原因。首先制作慢速版本,然后弄清楚如何加快速度。

其次,对于你的外循环,你真的只需要去sqrt(n)而不是n。

基本上,你有很多不相关的数字,所以对于每一个你都必须检查它是否是素数。

如果您事先知道数字的范围,您可以生成可以在该范围内(或其sqrt)发生的所有素数,并测试容器中的每个数字以便将其除以任何一个生成的素数。

生成素数最好由Erathostenes Sieve完成 - 可以找到该算法的许多例子。

您应该尝试使用净筛。您需要知道创建筛子的最大数量(O(n)),然后您可以在该范围内构建一组质数(O(max_element)或问题状态O(1000) == O(1)))并检查每个数字是否在一套素数。

您的代码完全错误。首先,你正在测试i%v [j] == 0,这是向后的,也解释了为什么你得到所有数字。其次,当您在每次失败(破损)可分性测试失败时测试并输出每个输入数字时,您的输出将包含重复项。

其他建议:

使用n作为向量中的最大值,向量中的元素数量令人困惑且毫无意义。您不需要传递向量中的元素数量 - 您只需查询向量的大小。并且你可以很快地找出最大值(但如果你提前知道它也可以将其传递出来)。

如上所述,你只需要测试到sqrt(n)[其中n是vecotr中的最大值]

您可以使用筛子生成最多n的所有素数,然后从输入向量中删除这些值,如上所述。这可能更快更容易理解,特别是如果你将素数存储在某个地方。

如果您要单独测试每个数字(使用,我猜和反筛),那么我建议按顺序单独测试每个数字。恕我直言,它比你写它的方式更容易理解 - 用k <!> lt;测试每个数字的可分性。 n不断增加k。

你试图实施的筛子的想法取决于你从一个素数(2)开始并跨越那个数量的大多数这一事实 - 所以所有数字都依赖于素数<!>“2 <! > QUOT;事先排除了。

那是因为所有非素数都可以分解为素数。虽然素数不能用模0整除,除非你将它们除以1或它们自己。

因此,如果你想依赖这个算法,你需要一些方法来实际恢复算法的这个属性。

您的代码似乎有很多问题:

  1. 如果你想测试你的号码是素数还是非素数,你需要检查v [j]%i == 0,而不是反过来
  2. 您没有检查您的电话号码是否自行划分
  3. 你一次又一次地检查你的号码。那是非常低效的。
  4. 正如其他人所说,你需要做一些像Eratosthenes的Sieve。

    因此,您的问题的伪C代码将是(我还没有通过编译器运行,所以请忽略语法错误。此代码仅用于说明算法)

    vector<int> inputNumbers;
    
    // First, find all the prime numbers from 1 to n
    bool isPrime[n+1] = {true};
    isPrime[0]= false;
    isPrime[1]= false;
    for (int i = 2; i <= sqrt(n); i++)
    {
      if (!isPrime[i])
        continue;
      for (int j = 2; j <= n/i; j++)
        isPrime[i*j] = false;
    }
    
    // Check the input array for non-prime numbers
    for (int i = 0; i < inputNumbers.size(); i++)
    {
       int thisNumber = inputNumbers[i];
       // Vet the input to make sure we won't blow our isPrime array
       if ((0<= thisNumber) && (thisNumber <=n))
       {
          // Prints out non-prime numbers
          if (!isPrime[thisNumber])
             cout<< thisNumber;
       }
    }
    

首先对数字进行排序可能是一个好的开始 - 你可以在nLogN时间内完成。这是对你的另一个问题的一个小的补充(我认为) - 找到一个数字是否为素数 (实际上,使用一小组数字,你可以使用vector / set大小的副本更快地进行排序,并进行哈希/桶分类/其他)

然后我会在集合中找到最高的数字(我假设数字可以无限制 - 在你的排序之前没有知道上限 - 或者只做一次通过以找到最大值)

然后去筛子 - 正如其他人所说的那样

Jeremy是对的,基本问题是你的i % v[j]而不是v[j] % i

试试这个:

void sieve(vector<int> v, int n) {
  int i,j;

  for(j = 0; j <= n; j++) {
    cout << v[j] << ": ";

    for(i = 2; i < v[j]; i++) {
      if(v[j] % i == 0) {
        cout << "is divisible by " << i << endl;
        break;
      }
    }

    if (i == v[j]) {
      cout << "is prime." << endl;
    }
  }
}

这不是最优的,因为它试图除以v[j]之外的所有数字而不是<=>的平方根。并且它试图通过所有数字而不仅仅是素数进行分割。

但它会奏效。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top