min and max running values

G

Gary Wessle

Hi

often I need to read numbers and only keep the highest or lowest.
so I do something like
int uLimit = 0;
int lLimit = 999999999999; //hoping the compiler will not complain

uLimit = val_read > uLimit ? val_read : uLimit;
lLimit = val_read < lLimit ? val_read : lLimit;

how do I choose the original lLimit?
is there more cleaver way?

thanks
 
V

Victor Bazarov

Gary said:
Hi

often I need to read numbers and only keep the highest or lowest.
so I do something like
int uLimit = 0;

'int' can be negative, you know...
int lLimit = 999999999999; //hoping the compiler will not complain

Why not just

int lLimit = INT_MAX; // or use std::numeric_limits<int>::max

?
uLimit = val_read > uLimit ? val_read : uLimit;
lLimit = val_read < lLimit ? val_read : lLimit;

how do I choose the original lLimit?
is there more cleaver way?

Clever? I don't know. Reliable more like it.

V
-
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
 
C

Clark Cox

Hi

often I need to read numbers and only keep the highest or lowest.
so I do something like
int uLimit = 0;

What about negative values?
int lLimit = 999999999999; //hoping the compiler will not complain

Why "hope"? Why not just get the value right to begin with?
uLimit = val_read > uLimit ? val_read : uLimit;
lLimit = val_read < lLimit ? val_read : lLimit;

how do I choose the original lLimit?

#include <limits>
#include <algorithm>

....

int uLimit = std::numeric_limits<int>::min();
int lLimit = std::numeric_limits<int>::max();

uLimit = std::max(val_read, uLimit);
lLimit = std::min(val_read, uLimit);
 
P

Pete Becker

Gary said:
Hi

often I need to read numbers and only keep the highest or lowest.
so I do something like
int uLimit = 0;
int lLimit = 999999999999; //hoping the compiler will not complain

uLimit = val_read > uLimit ? val_read : uLimit;
lLimit = val_read < lLimit ? val_read : lLimit;

how do I choose the original lLimit?

Use the first value of val_read for both limits.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
C

Clark Cox

Use the first value of val_read for both limits.

I would tend to disagree, as that would require a special case for the
first iteration of the loop.

i.e. I would prefer A to B:

/*A*/
int maxValue = std::numeric_limits<int>::min();
int minValue = std::numeric_limits<int>::max();

while( ... )
{
int input = getNextValue();
maxValue = std::max(maxValue, input);
minValue = std::min(minValue, input);

...
}

/*B*/
int input = getNextValue();
int maxValue = input;
int minValue = input;

do
{
input = getNextValue();
maxValue = std::max(maxValue, input);
minValue = std::min(minValue, input);
}
while(...);
 
P

Pete Becker

Clark said:
I would tend to disagree, as that would require a special case for the
first iteration of the loop.

i.e. I would prefer A to B:

Err, they do two different things. And, of course, they're written to
make A look better.
/*A*/
int maxValue = std::numeric_limits<int>::min();
int minValue = std::numeric_limits<int>::max();

while( ... )
{
int input = getNextValue();
maxValue = std::max(maxValue, input);
minValue = std::min(minValue, input);

...
}

/*B*/
int input = getNextValue();
int maxValue = input;
int minValue = input;

do
{
input = getNextValue();
maxValue = std::max(maxValue, input);
minValue = std::min(minValue, input);
}
while(...);

Let me present two versions that are biased the other way:

/*A*/
maxValue = std::numeric_limits<int>::min();
minValue = std::numeric_limits<int>::max();

while (...)
{
int input = getNextValue();
maxValue = std::max(maxValue, input);
minValue = std::min(minValue, input);
....
}

/*B*/
maxValue = minValue = getNextValue();

while (...)
{
int input = getNextValue();
maxValue = std::max(maxValue, input);
minValue = std::min(minValue, input);
....
}

Obviously B is vastly superior to the wordy, verbose, lengthy,
overwrought, wordy, redundant, and repetitive A. <g>

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
C

clarkcox3

Err, they do two different things. And, of course, they're written to
make A look better.






Let me present two versions that are biased the other way:

/*A*/
maxValue = std::numeric_limits<int>::min();
minValue = std::numeric_limits<int>::max();

while (...)
{
int input = getNextValue();
maxValue = std::max(maxValue, input);
minValue = std::min(minValue, input);
...

}

/*B*/
maxValue = minValue = getNextValue();

while (...)
{
int input = getNextValue();
maxValue = std::max(maxValue, input);
minValue = std::min(minValue, input);
...

}

Obviously B is vastly superior to the wordy, verbose, lengthy,
overwrought, wordy, redundant, and repetitive A. <g>

Even with this rewrite, I would still prefer A. I'd prefer not to do
the same thing in the loop setup as I do each iteration of the loop
(which was my main point; poorly stated as it was :) ). If all the
real code does is find the minimum and maximum then the difference is
trivial, but if something else needs to be done with the input then it
will have to be repeated; once in the loop's setup, and once in the
body of the loop.
 
R

Ron House

Clark said:
I would tend to disagree, as that would require a special case for the
first iteration of the loop.

But there _is_ a special condition for the first value - namely that
there be one! You cannot have a well-defined max or min of zero items.
So read the first value, check that you can get that first value and
complain somehow (err message, exception, etc.) if you can't, then make
it the starting running value for both max and min, and then have a loop
for any remaining values. That is the only way that is consistent with
the concept of what a max or a min actually is. Picking some hocum
'safe' starting value, even the min or max allowable value for the data
type, will give a broken answer (an answer claiming to be correct, but
which isn't) when there are no input items.
 
P

Pete Becker

Even with this rewrite, I would still prefer A. I'd prefer not to do
the same thing in the loop setup as I do each iteration of the loop
(which was my main point; poorly stated as it was :) ). If all the
real code does is find the minimum and maximum then the difference is
trivial, but if something else needs to be done with the input then it
will have to be repeated; once in the loop's setup, and once in the
body of the loop.

But all that was asked for was to find the minimum or the maximum, so
the possibility that one approach may be better than another in some
other situation isn't particularly pertinent. I'm really not interested
in generating a tutorial on when to do what, just in suggesting possible
approaches.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
V

Victor Bazarov

Ron said:
But there _is_ a special condition for the first value - namely that
there be one! You cannot have a well-defined max or min of zero items.

Why not? The sheer fact that min > max should tell you that there were
no items read. Am I missing something?
So read the first value, check that you can get that first value and
complain somehow (err message, exception, etc.) if you can't,

If you can't what? Complain? Read? Check?
then
make it the starting running value for both max and min, and then
have a loop for any remaining values. That is the only way that is
consistent with the concept of what a max or a min actually is.
Huh?

Picking some hocum 'safe' starting value, even the min or max
allowable value for the data type, will give a broken answer (an
answer claiming to be correct, but which isn't) when there are no
input items.

No, it won't. See above.

V
 
P

Pete Becker

Victor said:
Why not? The sheer fact that min > max should tell you that there were
no items read. Am I missing something?

The original request was not for a function that computes both min and
max, but was a general question about how to calculate them. Yes, if
you're doing both, you can use this hack. But it's not part of a general
solution for picking an initial value.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
C

Clark Cox

But there _is_ a special condition for the first value - namely that
there be one!

Who says that that is a necessery condition?
You cannot have a well-defined max or min of zero items. So read the
first value, check that you can get that first value and complain
somehow (err message, exception, etc.)

OK, so you check for error on reading the first value; do you then do
zero error checking on the second and subsequent values? No, you
*repeat the same error checking* (or a subset thereof); leading to
redundant code, which adds unneeded complexity and increases the
maintainence burden.
if you can't, then make it the starting running value for both max and
min, and then have a loop for any remaining values. That is the only
way that is consistent with the concept of what a max or a min actually
is. Picking some hocum 'safe' starting value, even the min or max
allowable value for the data type, will give a broken answer (an answer
claiming to be correct, but which isn't) when there are no input items.

No it won't, if min > max, then there obviously werent any input
values. That doesn't sound like a broken answer to me. It sounds like
a clearly identifiable error condition that leaves no room for
ambiguity.
 
P

Pete Becker

Clark said:
OK, so you check for error on reading the first value; do you then do
zero error checking on the second and subsequent values? No, you *repeat
the same error checking* (or a subset thereof); leading to redundant
code, which adds unneeded complexity and increases the maintainence burden.

Maybe. But it's also reasonable to simply say that calling a function
that returns the minimum value in a range of values with an empty range
produces undefined behavior. Implementations can check if they want to,
but aren't required to do anything sensible. After all, asking for the
minimum of no values is not a sensible request.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
K

Kai-Uwe Bux

Pete said:
Maybe. But it's also reasonable to simply say that calling a function
that returns the minimum value in a range of values with an empty range
produces undefined behavior. Implementations can check if they want to,
but aren't required to do anything sensible. After all, asking for the
minimum of no values is not a sensible request.

There is nothing non-sensible about defining the value of an associative
operation for an empty range of operands; in fact, it makes life much
easier, and we do it all the time for operations like + and *. The
convention, stolen from mathematics, is always that an associative
operation applied to an empty list of operands yields the identity element
with respect to the operation:

empty sum = 0 (this yields the meaning of a*0 = 0)
empty product = 1 (this yields the meaning of a^0 = 1)
empty union = empty_set
empty intersection = all class (or some problem specific universal set)

The convention ensures that the splitting

sum{ index in [a,b) } + sum{ index in [b,c) } = sum{ index in [a,c) }

holds even if a=b or b=c.

Therefore, it is quite natural to define

empty max = minimum possible value
empty min = maximum possible value

if you are in a situation where a minimum/maximum possible value exits.


Best

Kai-Uwe Bux
 
C

Clark Cox

Maybe. But it's also reasonable to simply say that calling a function
that returns the minimum value in a range of values with an empty range
produces undefined behavior. Implementations can check if they want to,
but aren't required to do anything sensible. After all, asking for the
minimum of no values is not a sensible request.

std::min_element seems to think that it is a perfectly sensible
request, with a well-defined return value.
 
P

Pete Becker

Kai-Uwe Bux said:
Therefore, it is quite natural to define

empty max = minimum possible value
empty min = maximum possible value

if you are in a situation where a minimum/maximum possible value exits.

Sure3, if that's what the application's design requires. But since we
don't have a design specification, it's not possible to choose the most
appropriate approach.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
P

Pete Becker

Clark said:
std::min_element seems to think that it is a perfectly sensible request,
with a well-defined return value.

Yes, because min_element takes iterators and follows the conventions of
STL algorithms. There are other ways to design functions, and in the
absence of any requirements, it's not possible to decide whether one
approach is better than another.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
P

Pete Becker

Clark said:
std::min_element seems to think that it is a perfectly sensible request,
with a well-defined return value.

Of course. And the return value is an iterator that tells you there is
no minimum, not an artificially created "minimum" value.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
P

Pete Becker

Clark said:
std::min_element seems to think that it is a perfectly sensible request,
with a well-defined return value.

Okay, third reply to this message. <g> std::min_element is a good
example of a context where the most straightforward implementation
doesn't use an artificial minimum value. Here's how it's most naturally
implemented (using int* instead of iterators, to simplify some of the
code in irrelevant ways):

int *min_element(int *first, int *last)
{
if (first == last)
return last;
int *val = first++;
while (first != last)
{
if (*first < *val)
val = first;
++first;
}
return val;
}

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 

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,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top