我有一系列随机数。范围实际上由用户确定,但最多为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;
}
}
}
答案 0 :(得分:9)
在此代码中:
if(i % v[j] == 0)
cout << v[j] << endl;
您正在测试索引以查看它是否可被v [j]整除。我认为你的意思是反过来,即:
if(v[j] % i == 0)
现在,你正在打印i的随机除数。您不打印已知不是素数的随机数。此外,您的输出中将有重复项,也许这没关系。
答案 1 :(得分:4)
首先,我认为Knuth首先说:过早优化是造成许多错误的原因。首先制作慢速版本,然后弄清楚如何加快速度。
其次,对于你的外循环,你真的只需要去sqrt(n)而不是n。
答案 2 :(得分:2)
基本上,你有很多不相关的数字,所以对于每一个你都必须检查它是否是素数。
如果您事先知道数字的范围,您可以生成可以在该范围内(或其sqrt)发生的所有素数,并测试容器中的每个数字以便将其除以任何一个生成的素数。
生成素数最好由Erathostenes Sieve完成 - 可以找到该算法的许多例子。
答案 3 :(得分:1)
您应该尝试使用prime sieve。您需要知道创建筛子的最大数量(O(n)
),然后您可以在该范围内构建一组素数(O(max_element)
或问题状态O(1000) == O(1)
))并检查是否每个数字都在素数集中。
答案 4 :(得分:1)
您的代码完全错误。首先,你正在测试i%v [j] == 0,这是向后的,也解释了为什么你得到所有数字。其次,当您在每次失败(破损)可分性测试失败时测试并输出每个输入数字时,您的输出将包含重复项。
其他建议:
使用n作为向量中的最大值,向量中的元素数量令人困惑且毫无意义。您不需要传递向量中的元素数量 - 您只需查询向量的大小。并且你可以很快地找出最大值(但如果你提前知道它也可以将其传递出来)。
如上所述,你只需要测试到sqrt(n)[其中n是vecotr中的最大值]
您可以使用筛子生成最多n的所有素数,然后从输入向量中删除这些值,如上所述。这可能更快更容易理解,特别是如果你将素数存储在某个地方。
如果您要单独测试每个数字(使用,我猜和反筛),那么我建议按顺序单独测试每个数字。恕我直言,它比你写它的方式更容易理解 - 用k&lt;来测试每个数字的可分性。 n不断增加k。
答案 5 :(得分:0)
你试图实施的筛子的想法取决于你从一个素数(2)开始并跨越那个数量的大多数这一事实 - 因此所有依赖于素数“2”的数字都被预先排除。
那是因为所有非素数都可以分解为素数。虽然素数不能用模0整除,除非你将它们除以1或它们自己。
因此,如果你想依赖这个算法,你需要一些方法来实际恢复算法的这个属性。
答案 6 :(得分:0)
您的代码似乎有很多问题:
正如其他人所说,你需要做一些像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;
}
}
答案 7 :(得分:0)
首先对数字进行排序可能是一个好的开始 - 你可以在nLogN时间内完成。这是对你的另一个问题的一个小补充(我认为) - 找到一个数字是否为素数 (实际上,使用一小组数字,你可以使用vector / set的大小副本更快地进行排序,并进行哈希/桶分类/其他)
然后我会在集合中找到最高的数字(我假设数字可以无限制 - 在你的排序之前没有知道上限 - 或者只做一次通过以找到最大值)
然后去筛子 - 正如其他人所说的那样
答案 8 :(得分:0)
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]
以外的所有数字,而不是仅仅v[j]
的平方根。并且它试图通过所有数字而不仅仅是素数进行分割。
但它会奏效。