2

I found the following code in a program example:

const unsigned int n = /* something */
unsigned int i = 1;
for (unsigned int j = 1; j < n-1; ++j) {
    i <<= 1;
}

Is there a direct formula to compute i from n without a loop ?

Vincent
  • 57,703
  • 61
  • 205
  • 388

2 Answers2

3

You can use:

i = 1 << (n - 2);

or more strict:

#include <limits.h> /* for CHAR_BIT */

const unsigned int n = /* something */;
unsigned int i  = 1;

if( (n - 2) > 0 && (n - 2) < (sizeof(i) * CHAR_BIT) ) {
  i = 1 << (n - 2);
}
3

More accurately:

assuming unsigned int is 16 bits (minimum as specified by C++ standard)

i = ( n < 18 ) ? ( ( n >= 2 ) ? ( 1 << (n-2) ) : 1 ) : 0;
Abhishek Bansal
  • 12,589
  • 4
  • 31
  • 46
  • 1
    +1 Exactly -- Shift by negative value is undefined at best. http://stackoverflow.com/questions/4945703/left-shifting-with-a-negative-shift-count – Aki Suihkonen Nov 17 '13 at 13:54
  • 2
    @AkiSuihkonen: well, still incomplete though; if an `unsigned int` as 32 bits, then `1 << 40` will be undefined too; so you need to guard both against underflow and overflow. – Matthieu M. Nov 17 '13 at 13:56
  • 1
    But if `unsigned int` isn't 32 bits, then your magic number will be wrong. – Mike Seymour Nov 17 '13 at 14:07
  • @MikeSeymour Well I hope now it takes into account the minimum range specification as per C++ standard. However, the original code posted by OP didn't have this check either. – Abhishek Bansal Nov 17 '13 at 14:15
  • @AbhishekBansal: Indeed; it would be better to omit that check (documenting the precondition on `n`), or use a value calculated from `sizeof i`. Now, your magic number is wrong if `unsigned int` isn't 16 bytes. – Mike Seymour Nov 17 '13 at 14:17
  • @MikeSeymour: I would not say it's wrong; it is restricted, but technically correct, and without any more specification for a valid input range for `n` there is little what can do. – Matthieu M. Nov 17 '13 at 14:18
  • @MatthieuM.: Sorry, "wrong" was a simplification of "not a valid optimisation unless there are restrictions on the inputs that we don't know about". I usually try not to be too pedantic at the weekend; perhaps I should steer clear of SO today. – Mike Seymour Nov 17 '13 at 14:25