Search code examples
c++divisioninteger-division

Why is my double or int value is always 0 after division?


I'm fairly new to C++ and I'm experiencing some strange behaviour from a percentage increase method I am writing for some image editing software.

What I want to do is give the R G or B value of the current pixel and divide it by some modifier, then multiply it by the new value to return the percentage increase, fairly easy concept.

However, whenever I run my debugger, the return value is always 0, I thought this may be because I was trying to do operations which give negative numbers on an integer (or maybe a divide by zero could occur?), so I tried to use a double to store the output of the computation, however I've had no luck.

The code I'm struggling with is below:

int Sliders::getPercentageIncrease(int currPixel, int newValue, int modifier)
{
    // calculate return value
    double returnVal = (currPixel / modifier) * newValue;

    // Check we are returning a positive integer
    if(returnVal >= 0)
        return (int)returnVal;

    // Return a negative integer value
    return (int)(0 - returnVal);
}

What am I doing wrong here?

NOTE: I have checked values, of inputs in my debugger and I get stuff like:

currPixel = 30
newValue = 119
modifier = 200

From this I would expect an output of 18 (I am not concerned with returning decimal figures)


Solution

  • Your current calculation only involves integers and so will be affected by integer division (which truncates the result to the nearest integer value).

    (currPixel / modifier) * newValue
         |           |
          ---------------integer division e.g. 10/3 = 3, not 3.333
    

    The result is then cast to double, but the accuracy is lost before this point.

    Consider the following:

    #include <iostream>
    using namespace std;
    
    int main() {
        int val1 = 10;
        int val2 = 7;
        int val3 = 9;
    
        double outval1 = (val1 / val2) * val3;
        double outval2 = ((double)val1 / val2) * val3;
        cout << "without cast: " << outval1 << "\nwith    cast: "<< outval2 << std::endl;
    
        return 0;
    }
    

    The output of this is:

    without cast: 9
    with    cast: 12.8571
    

    See it here

    Note that the cast has to be applied in the right place:

    (double)(val1 / val2) * val3 == 9.0      //casts result of (val1/val2) after integer division
    (val1 / val2) * (double)val3 == 9.0      //promotes result of (val1/val2) after integer division
    ((double)val1 / val2) * val3 == 12.8571  //promotes val2 before division
    (val1 / (double)val2) * val3 == 12.8571  //promotes val1 before division
    

    Due to promotion of the other operands, if in doubt you can just cast everything and the resulting code will be the same:

    ((double)val1 / (double)val2) * (double)val3 == 12.8571  
    

    It is a little more verbose though.