# (-1) or (0)

## Recommended Posts

ZedFx    176
I have always wondered how people calculate or represent the largest possible number of an unsigned integer, as in C/C++ it can be different sizes on different platforms/chips and hence can have different maximum numerical values. So the question is this: what is the better/best way to calculate it ? I have come to conclusion that it is either ((unsigned int)(-1)) or (~0), however, I am not sure if the (-1) way will work on all chips and things like that.

##### Share on other sites
doynax    850
Well, ~0 should always work. But -1 won't work on one's complement machines.
What's wrong with UINT_MAX?

##### Share on other sites
Sneftel    1788
Technically it won't always work, since it relies on the architecture using two's-complement for representation of signed integers. Use UINT_MAX, which I believe is defined in limits.h for moderately recent C compilers.

##### Share on other sites
Use either

#include <limits> // C++// or#include <limits.h> // C

A compiler vendor is good at telling what is the maximum value of an int when using its compiler :)

unsigned int max_uint = std::numeric_limits<unsigned int>::max(); // C++// orunsigned int max_uint = UINT_MAX; // C

Regards,

##### Share on other sites
Use numeric_limits as was recommended if you need the value at runtime. If you need the value at preprocessing time, use UINT_MAX. If you need the value at compile-time, (0u - 1u) is guaranteed to work, or you can use ::boost::integer_traits if you have boost installed.

##### Share on other sites
doynax    850
Quote:
 Original post by SneftelTechnically it won't always work, since it relies on the architecture using two's-complement for representation of signed integers.
Quote:
 Original post by Polymorphic OOPIf you need the value at compile-time, (0u - 1u) is guaranteed to work, or you can use ::boost::integer_traits if you have boost installed.
What's wrong with the OPs other suggestion (~0)?

##### Share on other sites
Unless I'm completely clueless, I believe that numeric_limits will work at compile time too - on VC++ implementation numeric_limits::max() is just an alias to the corresponding define, so I guess that a good compiler will probably transform it to a constant. I have no gcc here to verify if it is implemented in the same way.

Regards,

##### Share on other sites
Washu    7829
Quote:
 Original post by Emmanuel DelogetUnless I'm completely clueless, I believe that numeric_limits will work at compile time too - on VC++ implementation numeric_limits::max() is just an alias to the corresponding define, so I guess that a good compiler will probably transform it to a constant. I have no gcc here to verify if it is implemented in the same way.Regards,

Yes, the values of numeric limits will work at compile time.

##### Share on other sites
Quote:
Original post by doynax
Quote:
 Original post by SneftelTechnically it won't always work, since it relies on the architecture using two's-complement for representation of signed integers.
Quote:
 Original post by Polymorphic OOPIf you need the value at compile-time, (0u - 1u) is guaranteed to work, or you can use ::boost::integer_traits if you have boost installed.
What's wrong with the OPs other suggestion (~0)?

1) it is not really easy to decipher (are you sure you'll remember what you tried to do in 2 years?)

2) there is more standard way to do it

But you are true, it should work. I believe Sneftel considered only the (-1) trick, not the (~0) one.

##### Share on other sites
Quote:
 Original post by doynaxWhat's wrong with the OPs other suggestion (~0)?

Yeah, that should work too, I should have clarified.

Quote:
 Original post by Emmanuel DelogetUnless I'm completely clueless, I believe that numeric_limits will work at compile time too

Quote:
 Original post by WashuYes, the values of numeric limits will work at compile time.

Function call results, such as of those in numeric_limits specializations, are never useable at compile-time. In fact, that's precisely why boost has integer_traits.

##### Share on other sites
Washu    7829
Quote:
Original post by Polymorphic OOP
Quote:
 Original post by doynaxWhat's wrong with the OPs other suggestion (~0)?

Yeah, that should work too, I should have clarified.

Quote:
 Original post by Emmanuel DelogetUnless I'm completely clueless, I believe that numeric_limits will work at compile time too

Quote:
 Original post by WashuYes, the values of numeric limits will work at compile time.

Function call results are never useable at compile-time. In fact, that's precisely why boost has integer_traits.

mmm, I didn't mean for template usage, probably should have clarified that, as that was not in the OPs question, the value of std::numeric_limits<unsigned int>::max() is defined as being UINT_MAX. The value will be available at compiletime when the compiler is performing optimizations and can hence be inlined. Decisions can be made at compiletime using numeric_limits<T>::max() however, you just need to use an if.

##### Share on other sites
Quote:
Original post by Polymorphic OOP
Quote:
 Original post by Emmanuel DelogetUnless I'm completely clueless, I believe that numeric_limits will work at compile time too

Function call results, such as of those in numeric_limits specializations, are never useable at compile-time. In fact, that's precisely why boost has integer_traits.

[crying] Do you mean I'm clueless ? [bawling]

##### Share on other sites
doynax    850
Quote:
 Original post by Emmanuel Deloget1) it is not really easy to decipher (are you sure you'll remember what you tried to do in 2 years?)
Really? I think it's a lot more straight forward than casting -1 into an unsigned type.
Quote:
 Original post by Emmanuel Deloget2) there is more standard way to do it
It's got to be more common than 0U-1 at least, and the -1 trick isn't portable.

So if you need to calculate it manually I still prefer ~0.

##### Share on other sites
Quote:
 Original post by doynaxSo if you need to calculate it manually I still prefer ~0.

Wait, actually, make sure you do ~0u. ~0 would be operating on a signed int and then would be followed by a conversion, and wouldn't be portable.

##### Share on other sites
Sneftel    1788
~0 will work, but I just thought of an even better way. Fully portable!

template<unsigned int I>struct max_uint_aux{    const static value = (I+1 < I) ? I : max_uint_aux<I+1>::value;};const static int max_uint = max_uint_aux<0>;

(it might take a little while to compile [grin])

##### Share on other sites
Washu    7829
Quote:
 Original post by Sneftel~0 will work, but I just thought of an even better way. Fully portable!*** Source Snippet Removed ***(it might take a little while to compile [grin])

I think you mean [grin]:
template<unsigned int I>struct max_uint_aux{    const static unsigned int value = (I+1 < I) ? I : max_uint_aux<I+1>::value;};const static unsigned int max_uint = max_uint_aux<0>::value;

##### Share on other sites
Quote:
 Original post by Sneftel~0 will work, but I just thought of an even better way.

I hope that was a joke :p

##### Share on other sites
Enigma    1410
Quote:
 Original post by Sneftel~0 will work, but I just thought of an even better way. Fully portable!*** Source Snippet Removed ***(it might take a little while to compile [grin])

Enigma

##### Share on other sites
Sneftel    1788
Quote:
 Original post by Washuunsigned int

Good point. Template horribleness requires dedication to details.

##### Share on other sites
ZQJ    496
I'd be very surprised if that compiles at all since I'd expect template processing to be done with a tree structure of some kind (who would implement tail recursion for templates?), you'd need a machine with a 64-bit address space but only 32-bit unsigned ints to have enough address space to do it, let alone enough RAM. Why not:

template<unsigned I> struct max_int_aux{static const unsigned value = I*2u < I ? 0 : std::max(max_int_aux<I*2>::value + I, max_int_aux<I*2>::value);};unsigned max_int = max_int_aux<1>;

That might actually compile. It also works for computers in any base because it's a binary subdivision method.

##### Share on other sites
Quote:
 Original post by ZQJThat might actually compile. It also works for computers in any base because it's a binary subdivision method.

That shouldn't come close to compiling on any system :p

##### Share on other sites
ZQJ    496
No, you're right it won't because std::max() can't be used there and gcc appears to evaluate both conditionals regardless of whether they're needed or not. However, this one does work:

template<bool T, unsigned A, unsigned B> struct static_max_aux{	static const unsigned value = 0;};template<unsigned A, unsigned B> struct static_max_aux<true, A, B>{	static const unsigned value = A;};template<unsigned A, unsigned B> struct static_max_aux<false, A, B>{	static const unsigned value = B;};template<unsigned A, unsigned B> struct static_max{	static const unsigned value = static_max_aux<(A>B), A, B>::value;};template<bool T, unsigned I> struct max_int_aux{	static const unsigned value = 0;};template<unsigned I> struct max_int_aux<true, I>{	static const unsigned value = static_max<max_int_aux<(I*2u > I), I*2u>::value + I, max_int_aux<(I*2u > I), I*2u>::value>::value;};unsigned max_int = max_int_aux<true, 1>::value;

##### Share on other sites
ZedFx    176
Quote:
 Original post by doynaxWhat's wrong with UINT_MAX?

Nothings wrong with it ;-)

(did you also know templates with recursions wont compile with MSVC++2002)

##### Share on other sites
Quote:
Original post by ZedFx
Quote:
 Original post by doynaxWhat's wrong with UINT_MAX?

Nothings wrong with it ;-)

(did you also know templates with recursions wont compile with MSVC++2002)

I think they do compile, you just might need to change the stack depth that the compiler uses for templates.

##### Share on other sites
ZedFx    176
Yes, you posted back on one of my previous topics, that It did compile it fine, are you using the 2003 version ?

These are the errors I get just using the default settings:
testa.cpp(4) : error C2677: binary '+' : no global operator found which takes type '' (or there is no acceptable conversion)        testa.cpp(6) : see reference to class template instantiation 'Sum<>' being compiledtesta.cpp(4) : error C2056: illegal expression

What are you doing differentally ?