【问题标题】:在没有参数的函数中生成新的素数[关闭]
【发布时间】:2022-01-23 07:32:47
【问题描述】:

我正在做一个问题,我需要制作一个没有参数的函数generatePrime。该函数在第一次调用时应该返回数字23(第二次),5(第三次)等等。

我有一种直觉,这应该用递归来完成。但我不确定如何制作没有参数的递归函数。


不过,这只是程序的一部分 - 整个程序本身应该返回一些 lowhigh 之间的素数(不包括它们)

int main(){
int low, high, i;
scanf("%d %d", &low, &high); // Boundaries of interval (low, high)
...
for (i = low + 1; i < high; i++){...}
...
};

int generatePrime(){
...}

【问题讨论】:

  • Re“我有一种直觉,这应该用递归来完成”:不,绝对不是。
  • @EricPostpischil 感谢您的回复。所以我有一个想法,每次调用函数时都增加素数,但是当它应该是 2 时,第一次调用呢?我不知道在最初设置 int prime = 2 后如何“跳过这个”?
  • 我有一种直觉,您必须使用(静态)表格,您会一遍又一遍地查阅。随着它的成长。
  • 我在这里没有看到实际的问题。你说你不知道如何写一个没有参数的递归generatePrime。但如果函数不需要递归,那就没问题了。

标签: c function for-loop recursion primes


【解决方案1】:

如果赋值确实需要您编写一个不带参数的函数,并且每次调用都返回一个连续的素数,那么您可能打算使用静态对象。以下是返回简单计数器的方法:

int GenerateCounter(void)
{
    static int counter = 0;
    return counter++;
}

使用类似的静态对象可以实现一个例程,该例程将返回从两个开始的连续素数。但是,如果它必须以用户提供的 low 值开头,则有以下三种选择:

  • low必须以某种方式传递给函数。如果不是作为参数,那么它必须通过函数和调用者都可以访问的某个对象,例如在任何函数之外声明的变量。这通常被认为是糟糕的设计,不是一个好的编程任务。
  • 该函数可以使用它的静态对象来了解它第一次被调用的时间,并且可以在该实例上从输入中读取低值并记住它(通过静态对象)。
  • main 例程可以重复调用GenerateCounter,并且只有在达到low 值后才开始打印其结果。这很浪费,而且不太可能是该作业的原意。

【讨论】:

  • 或者它可能是一个文件范围变量(static int counter = 0; 在文件范围内,而不是在函数内部,以便文件中的一些其他代码可以将其重置为零,以便生成器可以在同一个程序中重复使用。
  • 谢谢你,我真的很感激。我现在明白了。
【解决方案2】:

创建一个不带参数的递归函数没有多大意义,因为递归的全部意义在于函数参数随着每一级递归而变化。

如果您希望函数generatePrime 不带参数,但在调用时返回下一个素数,则该函数必须记住它返回的最后一个值。这可以通过在带有static storage duration 的变量中记住这个值来实现,例如全局变量或static 局部变量。由于您需要从函数main 和函数generatePrime 访问此变量,我建议使用全局变量。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>

static int next;

//This function returns true if the number is prime,
//otherwise false. This is a very simple, inefficient
//implementation. Better, more efficient algorithms exist,
//such as the Sieve of Eratosthenes.
bool isprime( int num )
{
    if ( num < 2 )
        return false;

    int max = (int)sqrt( num ) + 1;

    if ( max >= num )
        max = num - 1;

    for ( int i = 2; i <= max; i++ )
    {
        if ( num % i == 0 )
            return false;
    }

    return true;
}

int generatePrime()
{
    while ( !isprime( next ) )
        next++;

    return next++;
}

int main( void )
{
    int low, high, i;

    printf( "Please enter low and high value: " );

    if ( scanf("%d %d", &low, &high) != 2 )
    {
        printf( "invalid input!\n" );
        exit( EXIT_FAILURE );
    }

    next = low + 1;

    while ( ( i = generatePrime() ) < high )
        printf( "%d\n", i );
}

这个程序有以下输出:

Please enter low and high value: 2 30
2
3
5
7
11
13
17
19
23
29
Please enter low and high value: 100 200
101
103
107
109
113
127
131
137
139
149
151
157
163
167
173
179
181
191
193
197
199

请注意,这个程序将计算一个比打印多一个素数,这有点浪费。但是,由于您的任务要求函数 generatePrime 不接受任何参数,因此我没有看到任何简单的方法来解决此问题。

【讨论】:

    【解决方案3】:

    ...应该返回一些低和高之间的素数

    这里不需要递归。把这个想法放在一边。

    创建一个表 [0...high] 并应用 Sieve of Eratosthenes。因此,所有寻找的素数都被确定为第一步。

    // Pseudo code
    Form table [0... high], mark all true
    table[0] = table[1] = false
    Set prime = 2
    while (prime <= high/prime) {
      for (p=2*prime, p <= high, p += prime)
        mark table[p] = false
      starting at prime, walk list looking for next prime
    

    创建一个无参数函数,该函数从低位开始遍历已完成的表,以查找仍然是素数的条目。

    int low, high;
    
    int generatePrime(){
      static int current_prime;
      static char *table  = NULL;
      if (table == NULL) {
        table = malloc(high + 1);
    
        // Realize pseudo code discussed above here.
        // ...
    
        current_prime = low - 1;
      }
      // Find next prime
      while (!table[++current_prime]) {
        ;
      }
      return current_prime;
    }
    

    这将是形成素数 [低 ... 高] 的非常快速的解决方案。缺点:代码需要组成一个大数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-07
      • 1970-01-01
      • 2014-02-17
      • 1970-01-01
      相关资源
      最近更新 更多