2

Sorry for the bad title, but I had no idea of how to name it. I has solving some problems to practice and I came across this one. The challenge was to write a class for a box. So it had the longitude, height, and breadth. One of the methods was supposed to return the volume of the box. This is like a resume of it:

#include<bits/stdc++.h>

class Box {
private:
    int l,b,h;
public:
    Box(int L, int B, int H){
        l=L;b=B;h=H;
    }
    int CalculateVolume() {
        return b*l*h;
    } 
};

int main() {
    int l,b,h;
    std::cin << l << b << h;
    Box box(l, b, h);
    std::cout << box.CalculateVolume() << std::endl;
}

Then when it came time for the test cases it gave me an error.

Input: 1039 3749 8473
Output: -1355615565

So I said, ok the result is too big. Lets make the return type bigger.

    long long int CalculateVolume() {
        return b*l*h;
    } 
// No changes to the rest

And the result was the same, so I said: "Ok even bigger" and did this:

    unsigned long long int CalculateVolume() {
        return b*l*h;
    } 
// No changes to the rest
Input: 1039 3749 8473
Output: 18446744072353936051

To my delight I found the result was not negative. But checking with my calculator the result wasn't correct either. So I stored it in a variable to see what was happening.

    unsigned long long int CalculateVolume(){
        unsigned long long int volume = b*h*l;
        std::cout << volume << std::endl;
        return volume;
    } 
// No changes to the rest
Input: 1039 3749 8473
Output: 
18446744072353936051
18446744072353936051

I was not surprised by the output. In a last effort and I really don't know from where did the idea came from I did this:

    unsigned long long int CalculateVolume(){
        unsigned long long int volume = b*h;
        unsigned long long int a = volume * l;
        return a;
    } 
// No changes to the rest

And to my surprise I got the correct answer

Input: 1039 3749 8473
Output: 33004122803

But I really don't understand why. And most importantly, should I be doing this in my programs just in case it has to handle really big numbers? Or how should I handle this?

Nechemia Hoffmann
  • 2,118
  • 2
  • 12
  • 21
Pablochaches
  • 968
  • 10
  • 25
  • 4
    It didn't matter, that you were increasing the size of the resulting variable. If the types of `l,b,h;` weren't changed - were `int` - the `int` maths were performed, and only the result were casted to a larger type. Note: signed integer overflows are undefined behavior. – Algirdas Preidžius May 04 '20 at 23:18
  • 2
    Tip: Try and get in the habit of using [constructor lists](https://en.cppreference.com/w/cpp/language/initializer_list) instead of assignment. – tadman May 04 '20 at 23:18
  • 3
    The the type of the resulting value only depends on the operands. If you multiply two ints, you get an int, even if you assign the result to a larger type. The `b * h * l` is computed using ints because `b`, `h`, and `l` are all ints. – eesiraed May 04 '20 at 23:20
  • 1
    Recommended reading: [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h). – HolyBlackCat May 04 '20 at 23:37

1 Answers1

-1

Really thanks for the help.

TIL that if the variables are ints it does not matter that the result of an operation is assigned to a long long int, the operation will be done with int maths.

So the ad hoc solution that i had worked because b*h was still an integer with no problems and when i then multiplied it by l it was alredy operating them as long long ints. This will be the final solution:

#include<bits/stdc++.h>

class Box {
private:
    long long int l,b,h;
public:
    Box(int L, int B, int H){
        l=L;b=B;h=H;
    }
    long long int CalculateVolume() {
        return b*l*h;
    } 
};

int main() {
    int l,b,h;
    std::cin >> l >> b >> h;
    Box box(l, b, h);
    std::cout << box.CalculateVolume() << std::endl;
}

Again, really thanks for your help.

Pablochaches
  • 968
  • 10
  • 25
  • 4
    Prefer `return 1ull*b*l*h;`, and leaving the individual items as `unsigned int`. (Also note, `unsigned long long` isn't always big enough) – Mooing Duck May 04 '20 at 23:38