Reputation: 4079
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)
Upvotes: 1
Views: 4511
Reputation: 1343
Since all three parameters are integer the result of the calculation
double returnVal = (currPixel / modifier) * newValue;
will always be truncated. Add cast to (double) and the result should be fine. Simply:
double returnVal = ((double)currPixel / modifier) * newValue;
If you only set a cast before the bracket the result of the division stays an integer.
Upvotes: 2
Reputation: 4409
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
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.
Upvotes: 3
Reputation: 36
casting to double should fix the error.
double returnVal = (double ) (currPixel) / (modifier) * newValue;
see type casting rules typecasting rules in c.
Upvotes: 0
Reputation: 18411
Do this:
// calculate return value
double returnVal = (static_cast<double>(currPixel) / modifier) * newValue;
Or this:
double returnVal = (currPixel / static_cast<double>(modifier)) * newValue;
As you know that operator /
will be performed first, and then the operator *
. I have typecasted one of the operands of /
to double
, and hence division will be performed double
. Now, left operand of *
would be double
(since /
produced double
), and the multiplication would be performed double
also. For clarity and correctness, you may write:
double returnVal = (static_cast<double>(currPixel) / static_cast<double>(modifier)) * static_cast<double>(newValue);
Or simply:
double returnVal = (double(currPixel) / (double)modifier) * (double)newValue;
But, following is WRONG:
double returnVal = (double)(currPixel / modifier) * /*(double)*/ newValue;
Since the division would be performed int
only! It is like:
double x = 10/3;
Where you need (either):
double x = 10.0/3;
double x = 10/3.0;
double x = (double)10/3;
Upvotes: 0
Reputation: 2882
As long as all values are in a range, let me say, less than 1000 and greater (or equal) than 0, which is common on colour values, do something like
int returnVal = (currPixel * newValue) / modifier
No need for doubles; it will even speed up the code.
Needless to say, modifier
should not be zero.
Upvotes: 0