Prime Sieve类或重载函数?

时间:2014-01-03 22:03:47

标签: c++ class overloading

目前我有两个功能:

  • 一个需要生成素数的数量。
  • 第二个采用素数的上限来生成。

它们被编码(在C ++中):

prime_list erato_sieve(ul_it upper_limit)
{
    prime_list primes;
    if (upper_limit < 2)
        return primes;
    primes.push_back(2); // Initialize Array, and add 2 since its unique.

    for (uit i = 3; i <= upper_limit; i += 2) // Only count odd numbers
    {
        flag is_prime = true;
        for (uit j = 0; j < primes.size(); ++j)
        {
            if ((i % primes[j]) == 0)
            {
                is_prime = false;
                break;
            }
        }
        if (is_prime)
        {
            primes.push_back(i);
        }
    }
    return primes;
}

prime_list erato_sieve_num(ul_it MAX)
{
    prime_list primes;
    if (MAX == 0)
        return primes;
    primes.push_back(2); // Initialize Array, and add 2 since its unique.

    uit i = 3;
    while (primes.size() < MAX) // Only count odd numbers
    {
        flag is_prime = true;
        for (uit j = 0; j < primes.size(); ++j)
        {
            if ((i % primes[j]) == 0)
            {
                is_prime = false;
                break;
            }
        }
        if (is_prime)
        {
            primes.push_back(i);
        }
        ++i;
    }
    return primes;
}

定义了以下类型:

typedef bool flag;
typedef unsigned int uit;
typedef unsigned long int ul_it;
typedef unsigned long long int ull_it;
typedef long long int ll_it;
typedef long double ld;

typedef std::vector<ull_it> prime_list;

(如果你愿意,可以随意使用它们。发现 - 替换会照顾它。我用它们来使代码更多地读取我的想法)

我试图将这些变成一个重载的“函数”,但它们两个有相似的参数。我担心它们之间的选择将归结为单独输入,这将导致难以调试的问题。

我的第二个选择是创建一个类,但我很尴尬地说..,我以前从未使用过类。完全没有。所以我不知道该怎么做,文档有点......稀疏?

无论如何,如果有人会介意帮助我一点点,我将不胜感激。文档总是有用的,也欢迎任何指针。

修改

正如我所说,我的部分选项是一个类。我完全相信如何组成一个课程来结合这两个。

3 个答案:

答案 0 :(得分:1)

永远不要给具有不同语义的函数赋予相同的名称。超载的目的不是为了这个目的。这两个都取整数,如果你可以重载它们,你怎么知道在erato_sieve(5)调用哪个函数?

给他们不同的名字,例如erato_sieve_up_toerato_sieve_count

好吧,如果你仍然想让事情变得更糟(请不要),你可以让他们超载(请不要),只是让他们期待不同类型的论点。例如,将一个整数包装到一个类中并传递该类,如

class CountWrapper {
 public:
  CountWrapper(int n) { n_ = n; }
  operator int() { return n_; }
 private:
  int n_;
};

prime_list erato_sieve(const CountWrapper& MAX) {
  // function's body stays the same

并称之为

my_list = erato_sieve(CountWrapper(5));

但又一次:请不要!

要对函数进行分组,可以将它们定义为类的静态方法:

class PrimeGenerator {
 public:
  static prime_list EratoSieveUpTo(ul_it upper_limit) {
    // body
  }

  static prime_list EratoSieveAmount(ul_it MAX) {
    // body
  }
};

并调用类似

的函数
list1 = PrimeGenerator::EratoSieveUpTo(5);
list2 = PrimeGenerator::EratoSieveAmount(10);

答案 1 :(得分:0)

如果要创建重载函数,则需要为每个函数定义使用不同的参数列表。在实际使用的参数是相同类型的情况下,可以使用以下技巧:

typedef struct {} flag_type_1;
typedef struct {} flag_type_2;
...
typedef struct {} flag_type_n;

prime_list erato_sieve(ul_it boundary, flag_type_1) { ... }
prime_list erato_sieve(ul_it boundary, flag_type_2) { ... }
...
prime_list erato_sieve(ul_it boundary, flag_type_n) { ... }

这个想法是每个类型定义的结构具有不同的类型签名。这为每个函数重载创建了完全不相关的参数列表。此外,由于类型是虚拟持有人,您不关心内容。这就是为什么你只需要在函数定义的参数列表中包含类型。

我从第9频道回来了一段时间。非常巧妙。

答案 2 :(得分:0)

这不是您问题的直接答案,但它有助于回答您的问题。

您似乎正在尝试实施Eratosthenes筛选。该筛子的基本算法如下:

1) Create a list of numbers from 2 to N (N is the maximum value you are looking for)
2) Start at 2, and eliminate all other even numbers (they are non-prime) less than or equal to N
3) Move to the next non-eliminated number.
4) Eliminate all multiples of that number less than or equal to N.
5) Repeat steps 3 and 4 until you reach the square root of N.

将其翻译成C ++代码,它看起来像这样(未优化):

std::vector<unsigned int> sieve_of_eratosthenes(unsigned int maximum)
{
    std::vector<unsigned int> results; // this is your result set
    std::vector<bool> tests(maximum + 1); // this will be your "number list"
    // initialize the tests vector
    for (unsigned int i = 0; i <= maximum; ++i)
    {
        if (i == 0 || i == 1)
            tests[i] = false;
        else
            tests[i] = true;
    }

    // eliminate all even numbers but 2
    for (unsigned int i = 4; i <= maximum; i += 2)
    {
        tests[i] = false;
    }

    // start with 3 and go to root of maximum
    unsigned int i = 3;
    while (i * i <= maximum)
    {
        for (unsigned int j = i + i; j <= maximum; j += i)
        {
            tests[j] = false;
        }

        // find the next non-eliminated value
        unsigned int k = i + 1;
        while (!tests[k])
        {
            k++;
        }
        i = k;
    }

    // create your results list
    for (unsigned int j = 0; j <= maximum; ++j)
    {
        if (tests[j])
        {
            results.push_back(j);
        }
    }

    return results;
}

Example

由于筛网需要最大值,因此您不希望为此算法提供许多素数。还有其他主要生成算法可以做到这一点,但是Eratosthenes的Sieve没有。