Sign in to follow this  
ZedFx

(-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 this post


Link to post
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 this post


Link to post
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++
// or
unsigned int max_uint = UINT_MAX; // C


Regards,

Share this post


Link to post
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 this post


Link to post
Share on other sites
doynax    850
Quote:
Original post by Sneftel
Technically 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 OOP
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.
What's wrong with the OPs other suggestion (~0)?

Share this post


Link to post
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 this post


Link to post
Share on other sites
Washu    7829
Quote:
Original post by Emmanuel Deloget
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,


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

Share this post


Link to post
Share on other sites
Quote:
Original post by doynax
Quote:
Original post by Sneftel
Technically 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 OOP
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.
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 this post


Link to post
Share on other sites
Quote:
Original post by doynax
What's wrong with the OPs other suggestion (~0)?

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

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


Quote:
Original post by Washu
Yes, 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 this post


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

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

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


Quote:
Original post by Washu
Yes, 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 this post


Link to post
Share on other sites
Quote:
Original post by Polymorphic OOP
Quote:
Original post by Emmanuel Deloget
Unless 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 this post


Link to post
Share on other sites
doynax    850
Quote:
Original post by Emmanuel Deloget
1) 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 Deloget
2) 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 this post


Link to post
Share on other sites
Quote:
Original post by doynax
So 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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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])

Reminds me of this thread.

Enigma

Share this post


Link to post
Share on other sites
Sneftel    1788
Quote:
Original post by Washu
unsigned int

Good point. Template horribleness requires dedication to details.

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
ZedFx    176
Quote:
Original post by doynax
What's wrong with UINT_MAX?


Nothings wrong with it ;-)

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

Share this post


Link to post
Share on other sites
risingdragon3    382
Quote:
Original post by ZedFx
Quote:
Original post by doynax
What'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 this post


Link to post
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 compiled
testa.cpp(4) : error C2056: illegal expression

What are you doing differentally ?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this