Min and max of a POD

A

Adem24

What is the best way to get the minimum value
and the maximum value an integral POD can hold
without using any external definitions like INT_MIN, INT_MAX etc.?
The type (short, int, long, etc.) plus signed/unsigned is known.
 
J

joseph cook

What is the best way to get the minimum value
and the maximum value an integral POD can hold
without using any external definitions like INT_MIN, INT_MAX etc.?
The type (short, int, long, etc.) plus signed/unsigned is known.

Why do you not want to use external definitions?
An alternative to those constants of course are from limits
i.e. numeric_limits<int>::max()

Joe Cook
 
H

Howard Hinnant

What is the best way to get the minimum value
and the maximum value an integral POD can hold
without using any external definitions like INT_MIN, INT_MAX etc.?
The type (short, int, long, etc.) plus signed/unsigned is known.

Would you be willing to make an assumption such as a two's complement
representation? Without some assumption like that, I see no way to
query the min/max without external definitions. With such an
assumption, the signed-ness can be queried without external
definitions as well.

-Howard
 
A

Adem24

Would you be willing to make an assumption such as a two's complement
representation? Without some assumption like that, I see no way to
query the min/max without external definitions. With such an
assumption, the signed-ness can be queried without external
definitions as well.

How would a solution for a two's complement representation look like?
 
T

Triple-DES

Just for the record, numeric_limits<int>::max() won't work under Visual
C++ because it defines two macros called "min" and "max", so the
preprocessor will try to expand the macro and the compiler will fail. It
really sucks.

Only if you include a non-standard header that defines those macros.

DP
 
T

Triple-DES

What is the best way to get the minimum value
and the maximum value an integral POD can hold
without using any external definitions like INT_MIN, INT_MAX etc.?
The type (short, int, long, etc.) plus signed/unsigned is known.

For the unsigned types, a conversion from -1 should yield the maximum
value.

unsigned u = -1;

DP
 
E

Eberhard Schefold

Fernando said:
Just for the record, numeric_limits<int>::max() won't work under Visual
C++ because it defines two macros called "min" and "max", so the
preprocessor will try to expand the macro and the compiler will fail. It
really sucks.

Just for the record, define NOMINMAX before including the Windows
headers, as described in MS KB article 143208.
 
J

James Kanze

Just for the record, numeric_limits<int>::max() won't work
under Visual C++ because it defines two macros called "min"
and "max", so the preprocessor will try to expand the macro
and the compiler will fail. It really sucks.

Funny, I don't have that problem when I compile with VC++. Of
course, like most compilers, by default, it doesn't compile C++,
but only something rather similar, but if you give it the
necessary options, there's no problem. (As a minimum, I think
you need -vmg -GR -EHs -Zc:forScope,wchar_t -DNOMINMAX
-D_CRT_SECURE_NO_DEPRECATE. Some of these may not be necessary
with more recent versions of the compiler, however, and there
may be others which I've missed---since I don't use this
compiler professionally, I'm not fully up to date with it.)
 
J

James Kanze

Would you be willing to make an assumption such as a two's
complement representation? Without some assumption like that,
I see no way to query the min/max without external
definitions. With such an assumption, the signed-ness can be
queried without external definitions as well.

For the unsigned, the representation of negative numbers is
irrelevant: the minimum is always 0, and the maximum
"~static_cast< Type >( 0 )" (or "static_cast< Type >( 0 ) - 1",
whichever you prefer).

For most systems, the maximum of a signed value can be obtained
by taking the maximum of the corresponding unsigned (as above),
then shifting it right 1 (still as unsigned). The minimum is a
bit tricky, but you should be able to do it by testing the 2
lower bits of -1, to add the special handling for 1's complement
and signed magnitude: I think the following should work:

- maximum - (static_cast< Type >( -1 ) & 3) == 3)

The only problem is on machines where the maximum value of an
unsigned is equal to the maximum value of the corresponding
signed. (The only two possibilities known to me are that the
unsigned uses the sign bit as part of its value, meaning that
shifting its max one to the right gives the max of a signed, or
that it ignores the sign bit, so that the max of the signed is
equal to the max of the unsigned. Regretfully, I don't know of
any way to determine which one holds, other than by using
external information. On the other hand, the only processor I
know where the unsigned simply ignore the sign bit is the Unisys
MCP, which isn't really a consideration for most people.)

In practice, of course, I use the constants defined in <climits>
if I need an integral constant expression, and the class
template numeric_limits (from <limits>) if I need the value for
a template argument. (And I wait until the next release of the
standard if I need both:).)
 
G

Gianni Mariani

Adem24 said:
What is the best way to get the minimum value
and the maximum value an integral POD can hold
without using any external definitions like INT_MIN, INT_MAX etc.?
The type (short, int, long, etc.) plus signed/unsigned is known.

Templates might work.

template <typename T, T V, T W, T X, T Y, bool Z=true>
struct max_val
{
static const T newv = V << 1;
static const T neww = W + newv;

static const T val = max_val<T, newv, neww, V, W, (newv > V)>::val;

};

template <typename T, T V, T W, T X, T Y>
struct max_val<T, V, W, X, Y, false>
{
static const T val = Y;
};

template <typename T>
struct maxof
{
static const T val = max_val<T,1,1,0,0,true>::val;
};


#include <iostream>

int main()
{
std::cout << "int " << maxof<int>::val << "\n";
std::cout << "unsigned int " << maxof<unsigned int>::val << "\n";
std::cout << "short " << maxof<short>::val << "\n";
std::cout << "char " << int(maxof<char>::val) << "\n";

}
 
A

Adem24

Gianni Mariani said:
Templates might work.

template <typename T, T V, T W, T X, T Y, bool Z=true>
struct max_val
{
static const T newv = V << 1;
static const T neww = W + newv;
static const T val = max_val<T, newv, neww, V, W, (newv > V)>::val;
};

template <typename T, T V, T W, T X, T Y>
struct max_val<T, V, W, X, Y, false>
{
static const T val = Y;
};

template <typename T>
struct maxof
{
static const T val = max_val<T,1,1,0,0,true>::val;
};


#include <iostream>
int main()
{
std::cout << "int " << maxof<int>::val << "\n";
std::cout << "unsigned int " << maxof<unsigned int>::val << "\n";
std::cout << "short " << maxof<short>::val << "\n";
std::cout << "char " << int(maxof<char>::val) << "\n";
}


This code seems to be too complicated for the Microsoft C++ compiler: :)

--------------------Configuration: test - Win32 Debug--------------------
Compiling...
test.cpp
C:\PRJ\test\test.cpp(3) : fatal error C1001: INTERNAL COMPILER ERROR
(compiler file 'msc1.cpp', line 1794)
Please choose the Technical Support command on the Visual C++
Help menu, or open the Technical Support help file for more information
Command line warning D4028 : minimal rebuild failure, reverting to normal build
Error executing cl.exe.
Creating browse info file...
BSCMAKE: warning BK4503 : minor error in .SBR file '.\Debug\test.sbr' ignored

test.exe - 1 error(s), 2 warning(s)
 
A

Adem24

Gianni Mariani said:
Templates might work.

template <typename T, T V, T W, T X, T Y, bool Z=true>
struct max_val
{
static const T newv = V << 1;
static const T neww = W + newv;
static const T val = max_val<T, newv, neww, V, W, (newv > V)>::val;
};

template <typename T, T V, T W, T X, T Y>
struct max_val<T, V, W, X, Y, false>
{
static const T val = Y;
};

I wonder if and when the 2nd max_val ever gets used at all...?
 
A

Adem24

Gianni Mariani said:
:


when (newv > V) is false.
It's the terminating condition.

And it really works on your machine?
Is the code you posted here correct or are any modification neccessary?
Which compiler and on which platform did you test it?
 
G

Gianni Mariani

And it really works on your machine? yes.

Is the code you posted here correct or are any modification neccessary?
afaict, yes.
Which compiler and on which platform did you test it?

I used gcc on cygwin (don't have machine with me so don't know gcc
version).
Also tested it just now on linux boxen with gcc 4.2.2.


Comeau says it's OK as well but has some overflow warnings which are
to be expected since this is a case of find out when the overflow
happens.

Comeau C/C++ 4.3.10.1 (May 29 2008 09:37:15) for
ONLINE_EVALUATION_BETA1
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 4: warning: integer conversion resulted in a
change of sign
static const T newv = V << T(1);
^
detected during:
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=short,
V=(short)16384, W=(short)32767, X=(short)8192,
Y=(short)16383, Z=true]" at line 7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=short,
V=(short)8192, W=(short)16383, X=(short)4096,
Y=(short)8191, Z=true]" at line 7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=short,
V=(short)4096, W=(short)8191, X=(short)2048,
Y=(short)4095, Z=true]" at line 7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=short,
V=(short)2048, W=(short)4095, X=(short)1024,
Y=(short)2047, Z=true]" at line 7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=short,
V=(short)1024, W=(short)2047, X=(short)512,
Y=(short)1023, Z=true]" at line 7
[ 6 instantiation contexts not shown ]
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=short,
V=(short)8, W=(short)15, X=(short)4, Y=(short)7,
Z=true]"
at line 7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=short,
V=(short)4, W=(short)7, X=(short)2, Y=(short)3,
Z=true]"
at line 7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=short,
V=(short)2, W=(short)3, X=(short)1, Y=(short)1,
Z=true]"
at line 7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=short,
V=(short)1, W=(short)1, X=(short)0, Y=(short)0,
Z=true]"
at line 21
instantiation of class "maxof<T> [with T=short]" at line
31

"ComeauTest.c", line 4: warning: integer conversion resulted in a
change of sign
static const T newv = V << T(1);
^
detected during:
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=char,
V='@', W='\177', X=' ', Y='?', Z=true]" at line
7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=char,
V=' ', W='?', X='\020', Y='\037', Z=true]" at
line 7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=char,
V='\020', W='\037', X='\b', Y='\017', Z=true]"
at line 7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=char,
V='\b', W='\017', X='\004', Y='\a', Z=true]" at
line 7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=char,
V='\004', W='\a', X='\002', Y='\003', Z=true]"
at line 7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=char,
V='\002', W='\003', X='\001', Y='\001', Z=true]"
at line
7
instantiation of class "max_val<T, V, W, X, Y, Z> [with
T=char,
V='\001', W='\001', X='\000', Y='\000', Z=true]"
at line
21
instantiation of class "maxof<T> [with T=char]" at line 32
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,279
Latest member
LaRoseDermaBottle

Latest Threads

Top