Mathematical operation to keep number not less than zero
Asked Answered
B

5

5

In programming, modulus is useful to keep numbers in range not exceeding an upper bound limit.

For example:

int value = 0;
for (int x=0; x<100; x++)
    cout << value++%8 << " "; //Keeps number in range 0-7

Output: 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7...


Now consider this situation:

int value = 5;
for (int x=0; x<100; x++)
    cout << value-- << " ";

Output: 5 4 3 2 1 0 -1 -2 -3 -4 -5 -6 -7...

My question is: How to set the lower bound limit to 0 WITHOUT using any conditional statement like if or switch case?

Output I want: 5 4 3 2 1 0 0 0 0 0 0 0 ...

Birkle answered 3/4, 2014 at 14:57 Comment(4)
Is it even possible? But I just feel that it is possible..Birkle
@TheForestAndTheTrees Please don't do that.Platonic
If I use unsigned int, I thought it will loop back to the max value like...65535 when it hits -1? :PBirkle
@Birkle If you like the negatives to be turned into positive integers you might be interested in std::abs(int) (coliru.stacked-crooked.com/a/0f0e6aa6243f114b) - And yes it might overflow with unsigned int.Platonic
B
6

How about std::max?

int value = 5;
for (int x=0; x<100; x++) {
    cout << value << " ";
    value = std::max(0, --value);
}
Bracing answered 3/4, 2014 at 15:3 Comment(4)
That's one possibility..hmm any other suggestion guys?Birkle
@Birkle How about accepting an answer or refining your requirements? I don't see why this isn't sufficient answer.Gerdy
@Gerdy Yes, his answer is fine. But I was looking for possibilites of using mathematical operations to get the solution.Birkle
max is a mathematical operation just as much as addition is. You give it two elements from an ordered set as input, and it returns an element from the same set. It's closed, and it even distributes over min.Bracing
C
2

Use std::max(value,0) or the ternary operator. Both will compile to code without conditional jumps.

Congregate answered 3/4, 2014 at 15:4 Comment(0)
B
1

Perhaps it can be done with

typedef unsigned u32b;

u32b sat_subu32b(u32b x, u32b y)
{
    u32b res = x - y;
    res &= -(res <= x); 
    return res;
}

which is taken from here. More specifically it seems to implement saturated subtraction; the saturated decrement would be

u32b sat_dec(u32bx)
{
    u32b res = x-1;
    res &= -(res <= x); 
    return res;
}

and seems to be branch-free.

Boudreaux answered 3/4, 2014 at 15:9 Comment(0)
B
0

The two situations are different. As you've shown, the % will make the numbers loop around from 0 to 7, whereas in the negative case you seem to be asking for the max.

Depending on whether you count the ternary operator as a conditional, you could do:

int value = 5;
for (int x=0; x<100; x++)
    cout << value > 0 ? value-- : 0 << " ";

This has the side effect that value will no longer be decremented once it has reached 0.

Alternatively, you could use a std::max:

int value = 5;
for (int x=0; x<100; x++)
    cout << std::max(0, value--) << " ";
Blabbermouth answered 3/4, 2014 at 15:9 Comment(0)
N
0

using max function in std.
max function detail:

template <class T> const T& max (const T& a, const T& b) {
  return (a<b)?b:a;     
}
Narcotism answered 3/4, 2014 at 16:40 Comment(2)
Now where have I seen that before? You should include your source and remove the comment as it makes no sense out of context.Blabbermouth
@Tom Fenech New user to this forum. I dont know i am required to attach the link. here we go, cplusplus.com/reference/algorithm/maxNarcotism

© 2022 - 2024 — McMap. All rights reserved.