min and max running values

Discussion in 'C++' started by Gary Wessle, Mar 5, 2007.

  1. Gary Wessle

    Gary Wessle Guest

    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
     
    Gary Wessle, Mar 5, 2007
    #1
    1. Advertisements

  2. 'int' can be negative, you know...
    Why not just

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

    ?
    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
     
    Victor Bazarov, Mar 5, 2007
    #2
    1. Advertisements

  3. Gary Wessle

    Clark Cox Guest

    What about negative values?
    Why "hope"? Why not just get the value right to begin with?
    #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);
     
    Clark Cox, Mar 5, 2007
    #3
  4. Gary Wessle

    qvasic Guest

    how do I choose the original lLimit?
    use std::numeric_limits<int>::max() and
    std::numeric_limits<int>::min().
     
    qvasic, Mar 5, 2007
    #4
  5. Gary Wessle

    Pete Becker Guest

    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)
     
    Pete Becker, Mar 5, 2007
    #5
  6. Gary Wessle

    Clark Cox Guest

    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(...);
     
    Clark Cox, Mar 6, 2007
    #6
  7. Gary Wessle

    Pete Becker Guest

    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>

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
     
    Pete Becker, Mar 6, 2007
    #7
  8. Gary Wessle

    clarkcox3 Guest

    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.
     
    clarkcox3, Mar 6, 2007
    #8
  9. Gary Wessle

    Ron House Guest

    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.
     
    Ron House, Mar 6, 2007
    #9
  10. Gary Wessle

    Pete Becker Guest

    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)
     
    Pete Becker, Mar 6, 2007
    #10
  11. Why not? The sheer fact that min > max should tell you that there were
    no items read. Am I missing something?
    If you can't what? Complain? Read? Check?
    No, it won't. See above.

    V
     
    Victor Bazarov, Mar 6, 2007
    #11
  12. Gary Wessle

    Pete Becker Guest

    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)
     
    Pete Becker, Mar 6, 2007
    #12
  13. Gary Wessle

    Clark Cox Guest

    Who says that that is a necessery condition?
    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.
    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.
     
    Clark Cox, Mar 6, 2007
    #13
  14. Gary Wessle

    Pete Becker Guest

    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)
     
    Pete Becker, Mar 6, 2007
    #14
  15. Gary Wessle

    Kai-Uwe Bux Guest

    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
     
    Kai-Uwe Bux, Mar 6, 2007
    #15
  16. Gary Wessle

    Clark Cox Guest

    std::min_element seems to think that it is a perfectly sensible
    request, with a well-defined return value.
     
    Clark Cox, Mar 6, 2007
    #16
  17. Gary Wessle

    Pete Becker Guest

    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)
     
    Pete Becker, Mar 6, 2007
    #17
  18. Gary Wessle

    Pete Becker Guest

    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)
     
    Pete Becker, Mar 6, 2007
    #18
  19. Gary Wessle

    Pete Becker Guest

    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)
     
    Pete Becker, Mar 6, 2007
    #19
  20. Gary Wessle

    Pete Becker Guest

    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)
     
    Pete Becker, Mar 6, 2007
    #20
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.