寻找合数
我有一系列随机数。 该范围实际上由用户确定,但最多可达 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;
}
}
}
I have a range of random numbers. The range is actually determined by the user but it will be up to 1000 integers. They are placed in this:
vector<int> n
and the values are inserted like this:
srand(1);
for (i = 0; i < n; i++)
v[i] = rand() % n;
I'm creating a separate function to find all the non-prime values. Here is what I have now, but I know it's completely wrong as I get both prime and composite in the series.
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;
}
}
}
This method typically worked when I just had a series of numbers from 0-1000, but it doesn't seem to be working now when I have numbers out of order and duplicates. Is there a better method to find non-prime numbers in a vector? I'm tempted to just create another vector, fill it with n numbers and just find the non-primes that way, but would that be inefficient?
Okay, since the range is from 0-1000 I am wondering if it's easier to just create vector with 0-n sorted, and then using a sieve to find the primes, is this getting any closer?
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;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
在此代码中:
您正在测试索引以查看它是否可以被 v[j] 整除。 我认为你打算以相反的方式来做,即:
现在,你正在打印 i 的随机除数。 您不会打印出已知不是质数的随机数。 另外,你的输出中会有重复的内容,也许这没关系。
In this code:
You are testing your index to see if it is divisible by v[j]. I think you meant to do it the other way around, i.e.:
Right now, you are printing random divisors of i. You are not printing out random numbers which are known not to be prime. Also, you will have duplicates in your output, perhaps that is ok.
首先,我认为 Knuth 首先说过:过早的优化是许多错误的原因。 先制作慢速版本,然后再想办法让它更快。
其次,对于外循环,您实际上只需要转到 sqrt(n) 而不是 n。
First off, I think Knuth said it first: premature optimization is the cause of many bugs. Make the slow version first, and then figure out how to make it faster.
Second, for your outer loop, you really only need to go to sqrt(n) rather than n.
基本上,您有很多不相关的数字,因此对于每个数字,您都必须检查它是否是素数。
如果您事先知道数字的范围,则可以生成该范围(或其开方)中可能出现的所有素数,并测试容器中的每个数字是否可以被以下任一数字整除生成的素数。
生成素数最好通过埃拉托斯特尼斯筛法来完成——该算法有很多例子。
Basically, you have a lot of unrelated numbers, so for each one you will have to check if it's prime.
If you know the range of the numbers in advance, you can generate all prime numbers that can occur in that range (or the sqrt thereof), and test every number in your container for divisibility by any one of the generated primes.
Generating the primes is best done by the Erathostenes Sieve - many examples to be found of that algorithm.
您应该尝试使用prime sieve。 您需要知道创建筛子的最大数量 (
O(n)
),然后您可以构建该范围内的一组素数 (O(max_element)
或作为问题指出O(1000) == O(1)
)) 并检查每个数字是否在素数集中。You should try using a prime sieve. You need to know the maximal number for creating the sieve (
O(n)
) and then you can build a set of primes in that range (O(max_element)
or as the problem statesO(1000) == O(1)
)) and check whether each number is in the set of primes.你的代码完全错误。 首先,您正在测试 i % v[j] == 0,这是向后的,也解释了为什么您得到所有数字。 其次,当您每次未通过(损坏的)整除性测试时测试和输出每个输入数字时,您的输出将包含重复项。
其他建议:
使用 n 作为向量中的最大值和向量中的元素数量是令人困惑且毫无意义的。 您不需要传递向量中的元素数量 - 您只需查询向量的大小。 您可以相当快地算出最大值(但如果您提前知道,您也可以将其传入)。
如上所述,您只需要测试 sqrt(n) [其中 n 是向量中的最大值]
您可以使用筛子生成最多 n 的所有素数,然后从输入向量中删除这些值,同样上面建议的。 这可能会更快、更容易理解,特别是如果您将素数存储在某处的话。
如果您要单独测试每个数字(我猜使用逆筛),那么我建议按顺序单独测试每个数字。 恕我直言,它比您编写的方式更容易理解 - 测试每个数字是否可以被 k < 整除。 n 不断增加 k。
Your code is just plain wrong. First, you're testing i % v[j] == 0, which is backwards and also explains why you get all numbers. Second, your output will contain duplicates as you're testing and outputting each input number every time it fails the (broken) divisibility test.
Other suggestions:
Using n as the maximum value in the vector and the number of elements in the vector is confusing and pointless. You don't need to pass in the number of elements in the vector - you just query the vector's size. And you can figure out the max fairly quickly (but if you know it ahead of time you may as well pass it in).
As mentioned above, you only need to test to sqrt(n) [where n is the max value in the vecotr]
You could use a sieve to generate all primes up to n and then just remove those values from the input vector, as also suggested above. This may be quicker and easier to understand, especially if you store the primes somewhere.
If you're going to test each number individually (using, I guess, and inverse sieve) then I suggest testing each number individually, in order. IMHO it'll be easier to understand than the way you've written it - testing each number for divisibility by k < n for ever increasing k.
您尝试实现的筛子的想法取决于这样一个事实:您从素数 (2) 开始并删除多个该数字 - 因此所有依赖于素数“2”的数字都被预先排除。
这是因为所有非素数都可以分解为素数。 而素数不能被模 0 整除,除非你将它们除以 1 或除以它们本身。
因此,如果你想依赖这个算法,你将需要一些手段来真正恢复算法的这个属性。
The idea of the sieve that you try to implement depends on the fact that you start at a prime (2) and cross out multitudes of that number - so all numbers that depend on the prime "2" are ruled out beforehand.
That's because all non-primes can be factorized down to primes. Whereas primes are not divisible with modulo 0 unless you divide them by 1 or by themselves.
So, if you want to rely on this algorithm, you will need some mean to actually restore this property of the algorithm.
你的代码似乎有很多问题:
正如其他人建议的那样,你需要做一些类似埃拉托斯特尼筛的事情。
因此,您的问题的伪 C 代码将是(我还没有通过编译器运行它,所以请忽略语法错误。此代码仅用于说明算法)
Your code seems to have many problems:
As other guys suggested, you need to do something like the Sieve of Eratosthenes.
So a pseudo C code for your problem would be (I haven't run this through compilers yet, so please ignore syntax errors. This code is to illustrate the algorithm only)
首先对数字进行排序可能是一个好的开始 - 您可以在 nLogN 时间内完成。 (我认为)这是对您的另一个问题的一个小补充 - 查找一个数字是否是素数。
(实际上,对于这样的一小组数字,您可以通过向量/集合大小的副本更快地进行排序,并进行哈希/桶排序/其他)
然后我会找到集合中的最大数字(我假设数字可以是无界的 - 在排序之前不知道上限 - 或者进行一次遍历来找到最大值)
然后用筛子 - 正如其他人所说
sorting the number first might be a good start - you can do that in nLogN time. That is a small addition (I think) to your other problem - that of finding if a number is prime.
(actually, with a small set of numbers like that you can do a sort much faster with a copy of the size of the vector/set and do a hash/bucket sort/whatever)
I'd then find the highest number in the set (I assume the numbers can be unbounded - no know upper limit until your sort - or do a single pass to find the max)
then go with a sieve - as others have said
Jeremy 是对的,基本问题是你的
i % v[j]
而不是v[j] % i
。试试这个:
它不是最佳的,因为它试图除以所有小于 v[j] 的数字,而不是仅除以
v[j]
的平方根。 它尝试除以所有数字而不仅仅是素数。但它会起作用。
Jeremy is right, the basic problem is your
i % v[j]
instead ofv[j] % i
.Try this:
It's not optimal, because it's attempting to divide by all numbers less than
v[j]
instead of just up to the square root ofv[j]
. And it is attempting dividion by all numbers instead of only primes.But it will work.