How to handle multiply operations for large number within a member function in following sample code

84 views Asked by At

I was following a tutorial and an assignment to calculate a volume of a box. for that purpose, following program is written.

class Box
{
private:
    int length{ 0 }, breadth{ 0 }, height{ 0 };

public:
    Box() {};
    Box(int l, int b, int h) :length{ l }, breadth{ b }, height{ h } {};
    Box(Box& B) :length{ B.length }, breadth{ B.breadth }, height{ B.height } {};
    ~Box() {}

    int getLength()
    {
        return length;
    }
    int const getBreadth() { return breadth; }
    int const getHeight() { return height; }
    long long const CalculateVolume() { return static_cast<long long> (length * breadth * height);}

    bool operator<(Box& bx)
    {
        return (CalculateVolume() < bx.CalculateVolume());
    };

    friend std::ostream& operator<<(ostream& out, Box& bx)
    {
        out << bx.length << " " << bx.breadth << " " << bx.height;
        return out;
    }
};



int main()
{
    Box bx1(1039, 3749, 8473);
    std::cout << "Volume = " << bx1.CalculateVolume() << std::endl;


    // Define the values
    int value1 = 1039;
    int value2 = 3749;
    int value3 = 8473;

    // Multiply the values together
    long long result = static_cast<long long>(value1) * value2 * value3;

    // Output the result
    std::cout << "Result of multiplication: " << result << std::endl;



    return 0;
}

in here, Volume is calculated incorrectly and following output is given.

Volume = -1355615565

but if I multiply the three values, I was able to get the correct values.

Result of multiplication: 33004122803

Seems like the value is exceeded the maximum value of the data type but I'm not able to find out the true reason. what is the issue in CalculateVolume() member function of the Box class. Any hints is welcome.

1

There are 1 answers

1
Frodyne On BEST ANSWER

Let us first observe that in both cases the three variables are ints. Next we look at the two snippets of code:

  • return static_cast<long long> (length * breadth * height);
  • long long result = static_cast<long long>(value1) * value2 * value3;

In the first piece the calculation is fully performed in the type of the variables (int), and then the result is cast to long long. This means that the calculation is done and overflowed before the cast is done.

In the second piece value1 is cast to long long first, and then the calculation is performed - but when you multiply int and long long, then the calculation is done in the larger type, and thus no overflow happens (as the result does fit in long long).

EDIT: Reply to comment.

The difference is in the placement of the parenthesis: cast(a) * b vs. cast(a * b). In your comment you still use the latter version:

long long const CalculateVolume() {
    long long result = static_cast<long long>(length * breadth * height);
    return result;
}

You could also do this:

long long const CalculateVolume() {
    long long temp = length;
    return temp * breadth * height;
}

The point is that when at least one operand in the multiplication is long long, then the entire calculation is done in that type.