0

I'm trying to exploit the fact that a vector of bools condenses storage to a single bit. The following recipe should be a good way to determine whether an int array contains repeats (Or is it? Is something inherently flawed about my whole idea?). I can't figure out why my compiler, XCode, is not liking the

INT_MAX - INT_MIN + 1

line of the following code. I tried casting the expression to a long, but I got the same warning. Any help is greatly appreciated!

bool contains_repeats_3(const std::vector<int>& V) { 
    std::vector<bool> bv (INT_MAX - INT_MIN + 1, 0); // <------ That's the problem line
    for (std::vector<int>::const_iterator it = V.begin() ; it != V.end(); ++it) {
        if (bv[*it - INT_MIN] == 1) {
            return true;
        } else { 
            bv[*it - INT_MIN] == 1;
        }
    }
   return false;    
}
7
  • What do you trying to achieve with INT_MAX - INT_MIN + 1? Isn't it always 0 theoretically? Commented Nov 8, 2013 at 6:49
  • @Drop: Why would it be 0 theoretically? Commented Nov 8, 2013 at 6:50
  • Isn't INT_MIN negative, so INT_MAX - INT_MIN + 1 = 2*INT_MAX +1? Commented Nov 8, 2013 at 6:51
  • @m0nk3y: Yes, INT_MIN is negative. So? Commented Nov 8, 2013 at 6:52
  • Do you konw that std::vector<bool> in C++ is already specialized to use just one bit per item? Commented Nov 8, 2013 at 6:56

2 Answers 2

3

Firstly, it is not the expression that you have to cast, it is the individual operands, as in (long) INT_MAX - (long) INT_MIN + 1. Casting just the first one is already sufficient.

Secondly, it is quite possible that the range of long is the same as the range of int on your platform, meaning that casting to long will not prevent overflow. You might have to cast to long long, assuming it is available to you.

Thirdly, are you sure you need a vector of that size? I hope std::vector<bool> is implemented as a bit-vector on your platform. Or at least that your platform is a 64-bit one. On a 32-bit platform you are pushing the limits of array size. Note that std::vector does not guarantee you this sort of capacity. You might want to expect bv.max_size() of your vector to see if it is even capable of holding that many elements.

Sign up to request clarification or add additional context in comments.

Comments

2

Fundamentally your problem is that INT_MAX is positive and INT_MIN is negative, so when you subtract MIN from MAX you're actually adding.

10 - -2 = 10 + 2 = 12

Then factor, the number you're adding to is already the largest number int can store while the number you're adding is the largest possible negative value. The difference between INT_MAX and 0 is INT_MAX, so the difference between INT_MAX and anything<0 is greater than INT_MAX.

(INT_MAX + 1) > INT_MAX
(INT_MAX - -1) > INT_MAX

Basically INT_MAX + anything>0 requires more bits to describe than there are in an int. This is overflow, the programming way of saying "carry one" (it only has one bit to annotate the carry, so it could be a lot more than one)

Imagine you have 2 bits to describe a signed number, four possible bit combinations: b00 (0), b01 (+1), b10 (-2), b11 (-1).

We assign -1 to b11 because b11 - b01 = b10 and b00 - b01 = b11+sign

As a result of this:

TINYINT_MAX = 1  (b01)
TINYINT_MIN = -2 (b10)

Here's how your formula works out:

(TINYINT_MAX - TINYINT_MIN +  1 )
 b01           b10           b01
( 1 - -2  +  1 )
 b01  b10   b01

( 1  +  2  +  1 ) <-- things go pear shaped here.
 b01   xxx   b01

( 3  +  1 )
 xxx   b01

= 4

We could handle "3" if we went unsigned, but 4 (b100) requires more bits than we have.

But our number system only supports +1, 0, -1, -2, so we were broken when we said "-TINYINT_MIN".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.