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
casting to double should fix the error.
double returnVal = (double ) (currPixel) / (modifier) * newValue;
see type casting rules typecasting rules in c.
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.
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;
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.
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.