Related
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)
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.
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.
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, modifiershould not be zero.
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;
casting to double should fix the error.
double returnVal = (double ) (currPixel) / (modifier) * newValue;
see type casting rules typecasting rules in c.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
strange output in comparison of float with float literal
When I am trying to compare 2 same float values it doesn't print "equal values" in the following code :
void main()
{
float a = 0.7;
clrscr();
if (a < 0.7)
printf("value : %f",a);
else if (a == 0.7)
printf("equal values");
else
printf("hello");
getch();
}
Thanks in advance.
While many people will tell you to always compare floating point numbers with an epsilon (and it's usually a good idea, though it should be a percentage of the values being compared rather than a fixed value), that's not actually necessary here since you're using constants.
Your specific problem here is that:
float a = 0.7;
uses the double constant 0.7 to create a single precision number (losing some precision) while:
if (a == 0.7)
will compare two double precision numbers (a is promoted first).
The precision that was lost when turning the double 0.7 into the float a is not regained when promoting a back to a double.
If you change all those 0.7 values to 0.7f (to force float rather than double), or if you just make a a double, it will work fine - I rarely use float nowadays unless I have a massive array of them and need to save space.
You can see this in action with:
#include <stdio.h>
int main (void){
float f = 0.7; // double converted to float
double d1 = 0.7; // double kept as double
double d2 = f; // float converted back to double
printf ("double: %.30f\n", d1);
printf ("double from float: %.30f\n", d2);
return 0;
}
which will output something like (slightly modified to show difference):
double: 0.6999999|99999999955591079014994
double from float: 0.6999999|88079071044921875000000
\_ different beyond here.
Floating point number are not what you think they are: here are two sources with more information: What Every Computer Scientist Should Know About Floating-Point Arithmetic and The Floating-Point Guide.
The short answer is that due to the way floating point numbers are represented, you cannot do basic comparison or arithmetic and expect it to work.
You are comparing a single-precision approximation of 0.7 with a double-precision approximation. To get the expected output you should use:
if(a == 0.7f) // check a is exactly 0.7f
Note that due to representation and rounding errors it may be very unlikely to ever get exactly 0.7f from any operation. In general you should check if fabs(a-0.7) is sufficiently close to 0.
Don't forget that the exact value of 0.7f is not really 0.7, but slightly lower:
0.7f = 0.699999988079071044921875
The exact value of the double precision representation of 0.7 is a better approximation, but still not exactly 0.7:
0.7d = 0.6999999999999999555910790149937383830547332763671875
a is a float; 0.7 is a value of type double.
The comparison between the two requires a conversion. The compiler will convert the float value to a double value ... and the value resulting from converting a float to a double is not the same as the value resulting from the compiler converting a string of text (the source code) to a double.
But don't ever compare floating point values (float, double, or long double) with ==.
You might like to read "What Every Programmer Should Know About Floating-Point Arithmetic".
Floating point numbers must not be compared with the "==" operator.
Instead of comparing float numbers with the "==" operator, you can use a function like this one :
//compares if the float f1 is equal with f2 and returns 1 if true and 0 if false
int compare_float(float f1, float f2)
{
float precision = 0.00001;
if (((f1 - precision) < f2) &&
((f1 + precision) > f2))
{
return 1;
}
else
{
return 0;
}
}
The lack of absolute precision in floats makes it more difficult to do trivial comparisons than for integers. See this page on comparing floats in C. In particular, one code snippet lifted from there exhibits a 'workaround' to this issue:
bool AlmostEqual2sComplement(float A, float B, int maxUlps)
{
// Make sure maxUlps is non-negative and small enough that the
// default NAN won't compare as equal to anything.
assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024);
int aInt = *(int*)&A;
// Make aInt lexicographically ordered as a twos-complement int
if (aInt < 0)
aInt = 0x80000000 - aInt;
// Make bInt lexicographically ordered as a twos-complement int
int bInt = *(int*)&B;
if (bInt < 0)
bInt = 0x80000000 - bInt;
int intDiff = abs(aInt - bInt);
if (intDiff <= maxUlps)
return true;
return false;
}
A simple and common workaround is to provide an epsilon with code like so:
if (fabs(result - expectedResult) < 0.00001)
This essentially checks the difference between the values is within a threshold. See the linked article as to why this is not always optimal though :)
Another article is pretty much the de facto standard of what is linked to when people ask about floats on SO.
if you need to compare a with 0.7 than
if( fabs(a-0.7) < 0.00001 )
//your code
here 0.00001 can be changed to less (like 0.00000001) or more (like 0.0001) > It depends on the precision you need.
I am using asin to calculate the angle. The code is as below :
double FindAngle(const double theValue)
{
return asin(theValue);
}
FindAngle returns a -0.0 (signed zero), when the argument theValue = -0.0. Now, how do i get rid of the minus sign from the return value.
You can do the following:
double FindAngle(const double theValue)
{
return (asin(theValue) + 0.0);
}
I had the same problem and that worked for me.
If you just want to convert -0 to 0 and leave other untouched, just do a comparison.
double FindAngle(double value) {
double res = asin(value);
if (res == 0.0) res = 0.0;
return res;
}
include <cmath> and use the abs function on your return value, if you want all results to be positive, or check if your return value is equal to -0.0 and take the abs value of it, for just that case.
abs function (c++ reference)
double FindAngle(const double theValue)
{
return abs(asin(value));
}
You can use the following method.
value = Float.compare(value, -0.0f) == 0 ? 0.0f : value ;
Are you sure that signed zero is your problem? (In this case, adding 0.0 to it—as proposed by FacundoJ above—would in fact solve it. Provided your arithmetic conforms to IEEE 754, that is.)
If, on the other hand, your problem is that printf("%f", x) produces -0.000000 (or similar for a similar format specifier), then just adding 0.0 is not enough: you will get the same output for any small, but negative, value.
In this case some actual programming is needed (at least I know of no better solution). I used something like this the other day:
int snrfmt(char *s, const char *format, double x)
{
int n, m;
char z[32];
n = sprintf(s, format, x);
m = sprintf(z, format, -DBL_MIN);
if (n == m && strcmp(s, z) == 0)
n = sprintf(s, format, 0.0);
return n;
}
as a kind-of replacement for sprintf():
double x = -1.23E-45;
char nr[80];
(void)snrfmt(buf, "%#+010.4f", x);
puts(nr);
This produces "+0000.0000" as desired (but of course "-0000.0001" for x = -0.50001E-4).
Can I rely on
sqrt((float)a)*sqrt((float)a)==a
or
(int)sqrt((float)a)*(int)sqrt((float)a)==a
to check whether a number is a perfect square? Why or why not?
int a is the number to be judged. I'm using Visual Studio 2005.
Edit: Thanks for all these rapid answers. I see that I can't rely on float type comparison. (If I wrote as above, will the last a be cast to float implicitly?) If I do it like
(int)sqrt((float)a)*(int)sqrt((float)a) - a < e
How small should I take that e value?
Edit2: Hey, why don't we leave the comparison part aside, and decide whether the (int) is necessary? As I see, with it, the difference might be great for squares; but without it, the difference might be small for non-squares. Perhaps neither will do. :-(
Actually, this is not a C++, but a math question.
With floating point numbers, you should never rely on equality. Where you would test a == b, just test against abs(a - b) < eps, where eps is a small number (e.g. 1E-6) that you would treat as a good enough approximation.
If the number you are testing is an integer, you might be interested in the Wikipedia article about Integer square root
EDIT:
As Krugar said, the article I linked does not answer anything. Sure, there is no direct answer to your question there, phoenie. I just thought that the underlying problem you have is floating point precision and maybe you wanted some math background to your problem.
For the impatient, there is a link in the article to a lengthy discussion about implementing isqrt. It boils down to the code karx11erx posted in his answer.
If you have integers which do not fit into an unsigned long, you can modify the algorithm yourself.
If you don't want to rely on float precision then you can use the following code that uses integer math.
The Isqrt is taken from here and is O(log n)
// Finds the integer square root of a positive number
static int Isqrt(int num)
{
if (0 == num) { return 0; } // Avoid zero divide
int n = (num / 2) + 1; // Initial estimate, never low
int n1 = (n + (num / n)) / 2;
while (n1 < n)
{
n = n1;
n1 = (n + (num / n)) / 2;
} // end while
return n;
} // end Isqrt()
static bool IsPerfectSquare(int num)
{
return Isqrt(num) * Isqrt(num) == num;
}
Not to do the same calculation twice I would do it with a temporary number:
int b = (int)sqrt((float)a);
if((b*b) == a)
{
//perfect square
}
edit:
dav made a good point. instead of relying on the cast you'll need to round off the float first
so it should be:
int b = (int) (sqrt((float)a) + 0.5f);
if((b*b) == a)
{
//perfect square
}
Your question has already been answered, but here is a working solution.
Your 'perfect squares' are implicitly integer values, so you could easily solve floating point format related accuracy problems by using some integer square root function to determine the integer square root of the value you want to test. That function will return the biggest number r for a value v where r * r <= v. Once you have r, you simply need to test whether r * r == v.
unsigned short isqrt (unsigned long a)
{
unsigned long rem = 0;
unsigned long root = 0;
for (int i = 16; i; i--) {
root <<= 1;
rem = ((rem << 2) + (a >> 30));
a <<= 2;
if (root < rem)
rem -= ++root;
}
return (unsigned short) (root >> 1);
}
bool PerfectSquare (unsigned long a)
{
unsigned short r = isqrt (a);
return r * r == a;
}
I didn't follow the formula, I apologize.
But you can easily check if a floating point number is an integer by casting it to an integer type and compare the result against the floating point number. So,
bool isSquare(long val) {
double root = sqrt(val);
if (root == (long) root)
return true;
else return false;
}
Naturally this is only doable if you are working with values that you know will fit within the integer type range. But being that the case, you can solve the problem this way, saving you the inherent complexity of a mathematical formula.
As reinier says, you need to add 0.5 to make sure it rounds to the nearest integer, so you get
int b = (int) (sqrt((float)a) + 0.5f);
if((b*b) == a) /* perfect square */
For this to work, b has to be (exactly) equal to the square root of a if a is a perfect square. However, I don't think you can guarantee this. Suppose that int is 64 bits and float is 32 bits (I think that's allowed). Then a can be of the order 2^60, so its square root is of order 2^30. However, a float only stores 24 bits in the significand, so the rounding error is of order 2^(30-24) = 2^6. This is larger to 1, so b may contain the wrong integer. For instance, I think that the above code does not identify a = (2^30+1)^2 as a perfect square.
I would do.
// sqrt always returns positive value. So casting to int is equivalent to floor()
int down = static_cast<int>(sqrt(value));
int up = down+1; // This is the ceil(sqrt(value))
// Because of rounding problems I would test the floor() and ceil()
// of the value returned from sqrt().
if (((down*down) == value) || ((up*up) == value))
{
// We have a winner.
}
The more obvious, if slower -- O(sqrt(n)) -- way:
bool is_perfect_square(int i) {
int d = 1;
for (int x = 0; x <= i; x += d, d += 2) {
if (x == i) return true;
}
return false;
}
While others have noted that you should not test for equality with floats, I think you are missing out on chances to take advantage of the properties of perfect squares. First there is no point in re-squaring the calculated root. If a is a perfect square then sqrt(a) is an integer and you should check:
b = sqrt((float)a)
b - floor(b) < e
where e is set sufficiently small. There are also a number of integers that you can cross of as non-square before taking the square root. Checking Wikipedia you can see some necessary conditions for a to be square:
A square number can only end with
digits 00,1,4,6,9, or 25 in base 10
Another simple check would be to see that a % 4 == 1 or 0 before taking the root since:
Squares of even numbers are even,
since (2n)^2 = 4n^2.
Squares of odd
numbers are odd, since (2n + 1)^2 =
4(n^2 + n) + 1.
These would essentially eliminate half of the integers before taking any roots.
The cleanest solution is to use an integer sqrt routine, then do:
bool isSquare( unsigned int a ) {
unsigned int s = isqrt( a );
return s * s == a;
}
This will work in the full int range and with perfect precision. A few cases:
a = 0, s = 0, s * s = 0 (add an exception if you don't want to treat 0 as square)
a = 1, s = 1, s * s = 1
a = 2, s = 1, s * s = 1
a = 3, s = 1, s * s = 1
a = 4, s = 2, s * s = 4
a = 5, s = 2, s * s = 4
Won't fail either as you approach the maximum value for your int size. E.g. for 32-bit ints:
a = 0x40000000, s = 0x00008000, s * s = 0x40000000
a = 0xFFFFFFFF, s = 0x0000FFFF, s * s = 0xFFFE0001
Using floats you run into a number of issues. You may find that sqrt( 4 ) = 1.999999..., and similar problems, although you can round-to-nearest instead of using floor().
Worse though, a float has only 24 significant bits which means you can't cast any int larger than 2^24-1 to a float without losing precision, which introduces false positives/negatives. Using doubles for testing 32-bit ints, you should be fine, though.
But remember to cast the result of the floating-point sqrt back to an int and compare the result to the original int. Comparisons between floats are never a good idea; even for square values of x in a limited range, there is no guarantee that sqrt( x ) * sqrt( x ) == x, or that sqrt( x * x) = x.
basics first:
if you (int) a number in a calculation it will remove ALL post-comma data. If I remember my C correctly, if you have an (int) in any calculation (+/-*) it will automatically presume int for all other numbers.
So in your case you want float on every number involved, otherwise you will loose data:
sqrt((float)a)*sqrt((float)a)==(float)a
is the way you want to go
Floating point math is inaccurate by nature.
So consider this code:
int a=35;
float conv = (float)a;
float sqrt_a = sqrt(conv);
if( sqrt_a*sqrt_a == conv )
printf("perfect square");
this is what will happen:
a = 35
conv = 35.000000
sqrt_a = 5.916079
sqrt_a*sqrt_a = 34.999990734
this is amply clear that sqrt_a^2 is not equal to a.
Hi i want to round double numbers like this (away from zero) in C++:
4.2 ----> 5
5.7 ----> 6
-7.8 ----> -8
-34.2 ----> -35
What is the efficient way to do this?
inline double myround(double x)
{
return x < 0 ? floor(x) : ceil(x);
}
As mentioned in the article Huppie cites, this is best expressed as a template that works across all float types
See http://en.cppreference.com/w/cpp/numeric/math/floor and http://en.cppreference.com/w/cpp/numeric/math/floor
or, thanks to Pax, a non-function version:
x = (x < 0) ? floor(x) : ceil(x);
There is a nice article about a similar problem on CPlusPlus.com. The easy solution to your problem should be something like this:
double customRound( double value ) const {
return value < 0 ? floor( value ) : ceil( value );
}
A better solution is the one mentioned in the article, which uses a template:
//--------------------------------------------------------------------------
// symmetric round up
// Bias: away from zero
template <typename FloatType>
FloatType ceil0( const FloatType& value )
{
FloatType result = std::ceil( std::fabs( value ) );
return (value < 0.0) ? -result : result;
}
The x < 0 ? floor(x) : ceil(x); approach of Ruben Bartelink is good. Yet consider what happens with special cases of x = -0.0, x = NaN.
Rather than have myround(-0.0) potentially return +0.01 and have myround(NaN) return with a changed payload of the NaN, consider the below.
myround_alt(-0.0) returns -0.0.
myround_alt(NaN) more likely returns an unchanged payload NaN. Not-a-number stuff is tricky and not well defined. IAC, it is the myround_alt(-0.0) --> -0.0 I am seeking.
inline double myround_alt(double x) {
if (x > 0) return ceil(x);
if (x < 0) return floor(x);
return x;
}
1IEC 60559 floating-point arithmetic specifies ceil(±0) returns ±0 so this approach not needed with implementations that strictly follow that spec. Yet many C floating point implementation do not follow that (C does not require it) or fail in such comer cases like this.
try
double rounded = _copysign(ceil(abs(x)), x);