venkysmarty
venkysmarty

Reputation: 11441

cyclic negative number generation in C++

I have requirement as follows.

I have to generate increment negative numbers from -1 to -100 which is used a unique id for a request. Like it should be like this: -1, -2, -3, ...-100, -1, -2, and so on. How can I do this effectively? I am not supposed to use Boost. C++ STL is fine. I prefer to write simple function like int GetNextID() and it should generate ID. Request sample program on how to do this effectively?

Thanks for your time and help

Upvotes: 0

Views: 118

Answers (4)

PaperBirdMaster
PaperBirdMaster

Reputation: 13298

I love the functor solution:

template <int limit> class NegativeNumber
{
public:
    NegativeNumber() : current(0) {};

    int operator()()
    {
        return -(1 + (current++ % limit));
    };
private:
    int current;
};

Then, you can define any generator with any limit and use it:

NegativeNumber<5> five;
NegativeNumber<2> two;

for (int x = 0; x < 20; ++x)
    std::cout << "limit five: " << five() << "\tlimit two: " << two() << '\n';

You can also pass the generator as parameter to another function, with each funtor with its own state:

void f5(NegativeNumber<5> &n)
{
    std::cout << "limit five: " << n() << '\n';
}

void f2(NegativeNumber<2> &n)
{
    std::cout << "limit two: " << n() << '\n';
}

f5(five);
f2(two);

If you don't like the template solution to declare the limit, there's also the no-template version:

class NegativeNumberNoTemplate
{
public:
    NegativeNumberNoTemplate(int limit) : m_limit(limit), current(0) {};

    int operator()()
    {
        return -(1 + (current++ % m_limit));
    };
private:
    const int m_limit;
    int current;
};

Using as argument to a function works in the same way, and it's internal state is transfered as well:

void f(NegativeNumberNoTemplate &n)
{
    std::cout << "no template: " << n() << '\n';
}

NegativeNumberNoTemplate notemplate(3);
f(notemplate);

I hope you don't want to use it with threading, they're not thread safe ;)

Here you have all the examples; hope it helps.

Upvotes: 2

David
David

Reputation: 2803

Even a simple problem like this could lead you to several approximations, both in the algorithmic solution and in the concrete usage of the programming language.

This was my first solution using C++03. I preferred to switch the sign after computing the value.

#include <iostream>

int GetNextID() {
    // This variable is private to this function. Be careful of not calling it
    // from multiple threads!
    static int current_value = 0;

    const int MAX_CYCLE_VALUE = 100;

    return - (current_value++ % MAX_CYCLE_VALUE) - 1;
}

int main()
{
    const int TOTAL_GETS = 500;

    for (int i = 0; i < TOTAL_GETS; ++i)
        std::cout << GetNextID() << std::endl;
}

A different solution taking into account that the integer modulo in C++ takes the sign of the dividend (!) as commented in the Wikipedia

#include <iostream>

int GetNextID() {
    // This variable is private to this function. Be careful of not calling it
    // from multiple threads!
    static int current_value = 0;

    const int MAX_CYCLE_VALUE = 10;

    return (current_value-- % MAX_CYCLE_VALUE) - 1;
}

int main()
{
    const int TOTAL_GETS = 50;

    for (int i = 0; i < TOTAL_GETS; ++i)
        std::cout << GetNextID() << std::endl;
}

Upvotes: 0

AnthonyLambert
AnthonyLambert

Reputation: 8830

Something like.... (haven't compiled)

class myClass
{
     int number = 0;
     int GetValue ()
     {
         return - (number = ((number+1) % 101))
     }
}

Upvotes: 0

Puppy
Puppy

Reputation: 146988

int ID = -1;
auto getnext = [=] mutable {
    if (ID == -100) ID = -1;
    return ID--;
};

Fairly basic stuff here, really. If you have to ask somebody on the Interwebs to write this program for you, you should really consider finding some educational material in C++.

Upvotes: 4

Related Questions