Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Positive integers that multiply to a negative value

Tags:

c++

integer

I am learning C++ by reading Stroustrup's "Principles and Practice Using C++".

In the section about pre- and post-conditions there is the following example of function:

int area(int length, int width)
// calculate area of a rectangle;
// pre-conditions: length and width are positive
// post-condition: returns a positive value that is the area
{
    if (length<=0 || width <=0) 
        error("area() pre-condition");

    int a = length*width;

    if (a<=0) 
        error("area() post-condition");

    return a;
}

What confused me is the task about this code:

Find a pair of values so that the pre-condition of this version of area holds, but the post-condition doesn’t.

Are there such possible values for integer that pre-conditions is ok but post-condition not?

like image 603
Pavel_K Avatar asked Dec 31 '15 11:12

Pavel_K


4 Answers

Are there such possible values for integer that pre-conditions is ok but post-condition not?

Yes there's a number of input values, that can cause the post condition to fail. If e.g.

int a = length*width;

overflows the positive int range (std::numeric_limits<int>::max()) and the compiler implementation yields a negative value for this case.


As others noted in their answers, the situation that length*width goes out of bounds from ]0-std::numeric_limits<int>::max()[ is actually undefined behavior, and the post condition renders merely useless, because any value might need to be expected for a.

The key point to fix this, is given in @Deduplicator's answer, the pre-condition needs to be improved.


As a lance for Bjarne Stroustrup's reasonings to give that example:

I assume he wanted to point out that such undefined behavior might lead to unexpected negative values in the post-condition and surprising results for a naive assumption checked with the pre-condition.

like image 87
πάντα ῥεῖ Avatar answered Oct 23 '22 07:10

πάντα ῥεῖ


No, there aren't any values that will, within the bounds of defined behavior of standard C++, violate the post-condition. However, there are values that still can make the function behave incorrectly, namely values so large that their product does not fit within an integer. Try passing 200'000 and 15'000.

Due to the way most compilers implement C++, you might see the post-condition being violated, but what you're actually observing is undefined behavior due to integer overflow.

like image 29
Sebastian Redl Avatar answered Oct 23 '22 07:10

Sebastian Redl


The answer is that his precondition-check is incomplete. Even though it is too restrictive.
He failed to include a check that the product can be represented instead of resulting in UB:

int area(int length, int width) {
    // calculate area of a rectangle
    assert(length >= 0 && width >= 0 && (!width
        || std::numeric_limits<int>::max() / width >= length));
    int a = length * width;
    assert(a >= 0); // Not strictly neccessary - the math is easy enough
    return a;
}
like image 31
Deduplicator Avatar answered Oct 23 '22 06:10

Deduplicator


What comes to my mind is a signed overflow. It is undefined behavior but might yield a negative value.
Try std::numeric_limits<int>::max() and 2.

like image 21
cadaniluk Avatar answered Oct 23 '22 07:10

cadaniluk