This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
when i divide two numbers inside an if statement and check for a condition, if goes false even if it should be true
if a directly type (w/h) inside if instead of s it gives wrong output.
given this input
5
10 1
165 100
180 100
170 100
160 100
it should give 3,
but if i give (w/h) inside if instead of s it gives output as 1
I dont get it, if becomes false even though statement is true.
#include<iostream>
using namespace std;
int main()
{
long long n,c=0;
cin>>n;
while(n--)
{
long double w,h;
cin>>w>>h;
double s = w/h;
if(s >=1.6 && s <=1.7) // if((w/h)>=1.6 &&(w/h)<=1.7) becomes false for w=170, h=100
{
c++;
}
}
cout<<c;
}
You are seeing different results because of mixing double and long double.
When you use:
if ( (w/h) >= 1.6 && (w/h) <= 1.7)
the term w/h is of type long double. For comparison, 1.6 and 1.7 are promoted to long double.
If you want to see the same results, use:
long double s = w/h;
if ( s >= 1.6 && s <= 1.7 )
Having said that, it's best to compare floating point numbers with some tolerance.
long double tolerenance = 1.0E-6; // I'm picking an aribtray number.
long double s = w/h;
if ( s >= (1.6 - tolerance) && s <= (1.7 + tolerance) )
if(s >=1.6 && s <=1.7) // if((w/h)>=1.6 &&(w/h)<=1.7) becomes false for w=170, h=100
When you have (w/h)<=1.7, you are directly using the result of division of 170.0L by 100.0L (i.e. two numbers of type long double), which is, on x86 gcc, equal to the following number (closest representation of 1.7 in long double)
1.70000000000000000004336808689942017736029811203479766845703125
You are then comparing it with 1.7, which is, when converted to actual value, approximated by the closest representable double (because the literal is of type double):
1.6999999999999999555910790149937383830547332763671875
Of course, the former is greater than the latter, so you get false.
OTOH, when you assign the result of division to s, it is rounded to the type of s, i.e. double, and then you compare the equal numbers, which gives you true.
Was your original statement like this:
if( w/h >= 1.6 && w/h <= 1.7) {
then try wrapping the w/h like this:
if( (w/h) >= 1.6 && (w/h) <= 1.7) {
Related
I am trying to solve Project Euler 94 first with brute force.
This requires me to work out whether an area of a given triangle is integral.
I do know the base and height, which are both integral.
long double area = 0.5*h*b;
When using double point arithmetic I arrive at answers which exceeds the exponent and sacrifices the precision of the fraction.
Is there any way for me to to ignore most significant part of the exponent and solely focus on fraction as I am only interested in whether the area is integral and not what size it is. Also I am using Visual Studio which I believe does not have long double just double?
EDIT
This is my code now. It reduced number of wrong triangles picked up by 3 from 26 to 23.
EDIT 2
I have read everyone's suggestions, but I am still not able to filter out the heights which are not integral my latest code looks like this. I know I am doing something really stupid but just can't pin point it.
void findAET(){
int gt = 0; //triangle count is
for(long long ss = 3; ss<333333334;ss+=2){ //skips out odd bases
for(int c = -1; c<2; c+=2){
long long base = c + ss;
if((sqrt((ss*ss)-(double)((base/2)*(base/2)))) == int(sqrt(((ss*ss))-(double)((base/2)*(base/2)))) ){ // check if height is an integer
if( (int)((sqrt((ss*ss)-(double)((base/2)*(base/2))))*base)%2==0){
cout<<" same sides "<<ss<<" base "<< base <<endl;
gt++;
}
}
}
}
}
}
As was mentioned in the comments, if bothh and b are both integer types, then 0.5*h*b has an integer result if either h or b are even:
if (((h % 2) == 0) || ((b % 2) == 0)) {
printf("area is integral\n");
} else {
printf("area is not integral\n");
}
If (b * h) % 2 == 0 then we know that (b * h) / 2 will be an integer result. Then all you need is a integer data type. I am not sure how big of a number you need to compute but a long long can hold up to 9223372036854775807 at 64 bits.
// Returns zero if height is not an integer
// Returns exact height if there is an exact height
// Relies on unsigned having at least 30 bits and long long at least 61
unsigned find_height( unsigned x, unsigned y){
if ( y & 1 ) return 0; // Height is not an integer because height squared is not
long long hs = (long long)x*x - (long long)y*y/4;
unsigned result = sqrt(hs) + .5;
if ( (long long)result*result != hs ) return 0;
return result;
}
If you compute height this way, you don't need any integer tests for area. Area will be an integer whenever height is an integer.
With a 60 bit integer input, sqrt(double) is accurate enough that the closest integer will be the correct integer when the true answer is an integer. But since a 60 bit integer can't really be held in a double, the test of whether the result of sqrt(double) is an integer can be incorrect in either direction from whether the true answer is an integer. But it is trivial to find out whether the closest integer (unsigned)(D+.5) is the true answer, by just squaring it and comparing.
Recently I decided to get into c++, and after going through the basics I decided to build a calculator using only iostream (just to challenge myself). After most of it was complete, I came across an issue with my loop for exponents. Whenever a multiple of Pi was used as the exponent, it looped way too many times. I fixed it in a somewhat redundant way and now I'm hoping someone might be able to tell me what happened. My unfixed code snippet is below. Ignore everything above and just look at the last bit of fully functioning code. All I was wondering was why values of pi would throw off the loop so much. Thanks.
bool TestForDecimal(double Num) /* Checks if the number given is whole or not */ {
if (Num > -INT_MAX && Num < INT_MAX && Num == (int)Num) {
return 0;
}
else {
return 1;
}
}
And then heres where it all goes wrong (Denominator is set to a value of 1)
if (TestForDecimal(Power) == 1) /* Checks if its decimal or not */ {
while (TestForDecimal(Power) == 1) {
Power = Power * 10;
Denominator = Denominator * 10;
}
}
If anyone could give me an explanation that would be great!
To clarify further, the while loop kept looping even after Power became a whole number (This only happened when Power was equal to a multiple of pi such as 3.1415 or 6.2830 etc.)
Heres a complete code you can try:
#include <iostream>
bool TestForDecimal(double Num) /* Checks if the number given is whole or not */ {
if (Num > -INT_MAX && Num < INT_MAX && Num == (int)Num) {
return 0;
}
else {
return 1;
}
}
void foo(double Power) {
double x = Power;
if (TestForDecimal(x) == 1) /* Checks if its decimal or not */ {
while (TestForDecimal(x) == 1) {
x = x * 10;
std::cout << x << std::endl;
}
}
}
int main() {
foo(3.145); // Substitute this with 3.1415 and it doesn't work (this was my problem)
system("Pause");
return 0;
}
What's wrong with doing something like this?
#include <cmath> // abs and round
#include <cfloat> // DBL_EPSILON
bool TestForDecimal(double Num) {
double diff = abs(round(Num) - Num);
// true if not a whole number
return diff > DBL_EPSILON;
}
The look is quite inefficient...what if Num is large...
A faster way could be something like
if (Num == static_cast<int>(Num))
or
if (Num == (int)Num)
if you prefer a C-style syntax.
Then a range check may be useful... it oes not make sense to ask if Num is an intger when is larger than 2^32 (about 4 billions)
Finally do not think od these numers as decimals. They are stored as binary numbers, instead of multiplying Power and Denominator by 2 you are better of multiplying them by 2.
Most decimal fractions can't be represented exactly in a binary floating-point format, so what you're trying to do can't work in general. For example, with a standard 64-bit double format, the closest representable value to 3.1415 is more like 3.1415000000000001812.
If you need to represent decimal fractions exactly, then you'll need a non-standard type. Boost.Multiprecision has some decimal types, and there's a proposal to add decimal types to the standard library; some implementations may have experimental support for this.
Beware. A double is (generally but I think you use a standard architecture) represented in IEE-754 format, that is mantissa * 2exponent. For a double, you have 53 bits for the mantissa part, one for the sign and 10 for the exponent. When you multiply it by 10 it will grow, and will get an integer value as soon as exponent will be greater than 53.
Unfortunately, unless you have a 64 bits system, an 53 bits integer cannot be represented as a 32 bits int, and your test will fail again.
So if you have a 32 bits system, you will never reach an integer value. You will more likely reach an infinity representation and stay there ...
The only use case where it could work, would be if you started with a number that can be represented with a small number of negative power of 2, for example 0.5 (1/2), 0.25(1/4), 0.75(1/2 + 1/4), giving almost all digits of mantissa part being 0.
After studying your "unfixed" function, from what I can tell, here's your basic algorithm:
double TestForDecimal(double Num) { ...
A function that accepts a double and returns a double. This would make sense if the returned value was the decimal value, but since that's not the case, perhaps you meant to use bool?
while (Num > 1) { make it less }
While there is nothing inherently wrong with this, it doesn't really address negative numbers with large magnitudes, so you'll run into problems there.
if (Num > -INT_MAX && Num < INT_MAX && Num == (int)Num) { return 0; }
This means that if Num is within the signed integer range and its integer typecast is equal to itself, return a 0 typecasted to a double. This means you don't care whether numbers outside the integer range are whole numbers or not. To fix this, change the condition to if (Num == (long)Num) since sizeof(long) == sizeof(double).
Perhaps the algorithm your function follows that I've just explained might shed some light on your problem.
I am trying to get the number of digits after a decimal point in a double. Currently, my code looks like this:
int num_of_decimal_digits = 0;
while (someDouble - someInt != 0)
{
someDouble = someDouble*10;
someInt = someDouble;
num_of_decimal_digits++;
}
Whenever I enter a decimal in for someDouble that is less than one, the loop gets stuck and repeats infinitely. Should I use static_cast? Any advice?
Due to floating-point rounding error, multiplying by 10 is not necessarily an exact decimal shift. You can test the absolute error of the difference rather than comparing it for exact equality with 0.
while (abs(someDouble - someInt) < epsilon)
Or you can acknowledge that a double with a 53-bit mantissa can only represent log10 253 ≈ 15.9 decimal digits, and limit the loop to 16 iterations.
while (someDouble - someInt != 0 && num_of_decimal_digits < 16)
Or both.
while (abs(someDouble - someInt) < epsilon && num_of_decimal_digits < 16)
The naive answer would be:
int num_of_decimal_digits = 0;
double absDouble = someDouble > 0 ? someDouble : someDouble * -1;
while (absDouble - someInt != 0)
{
absDouble = absDouble*10;
someInt = absDouble;
num_of_decimal_digits++;
}
This solves your problem of negative numbers.
However, this solution is likely not going to give you the output you desire in a lot of cases because of the way that floating point numbers are represented. For example 0.35 might really be represented as 0.3499999999998 the way floating point numbers are stored in binary. I would suggest that you share more background information about what you are hoping to accomplish with this code (your input and your desired output). There is likely a much better solution for what you are attempting to accomplish.
This question already has answers here:
Why does division result in zero instead of a decimal?
(5 answers)
Closed 9 years ago.
I am trying to do a simple calculation : ( (45/100) - (20+50)/200 )*(10+5)
I am expecting the answer to be 1.5 but when the programme is compiled , it shows 0.
Can someone figure this out for me
#include <iostream>
using namespace std;
int main()
{
float CivIndex = ( (45/100) - (20+50)/200 )
*(10+5);
cout<<CivIndex; // expect 1.5 but getting 0
}
Integer division!
(45 / 100) equals 0 when evaluated as an integer, not 0.45 as you'd been hoping.
Make either numerator or denominator a float to get the expected result:
(45.0 / 100)
What you are doing is integer division, and integer division rounds the result to the closest integer. To correct your code, change it to:
#include <iostream>
using namespace std;
int main()
{
float CivIndex = ( (45.0/100.0) - (20.0+50.0)/200.0 )
*(10.0+5.0);
cout<<CivIndex; // expect 1.5 but getting 0
}
Note: not all .0 are needed, but just put them to be sure.
You are doing integer division.
Specify it as float constants
float CivIndex = ( (45./100) - (20+50)/200. )*(10+5);
^ Notice decimal points^
All your constants are ints, therefore, the compiler is doing integer math. 45/100 as an int is 0. So is 70/200. 0 - 0*15 = 0. You need to tell the compiler that your constants are floats: 20f, or 20.0 would both work. (For each operation, if at least one constant is a float, the operation will be treated as floating point math.)
In C and several other languages diving two integers result in an integer (integral division). That is 45 / 100 in your code will result in 0 instead of the expected 0.45
The fix is simple: convert one of the operands to floating point.
float CivIndex = ( (45/100.0) - (20+50)/200.0 )
*(10+5);
You are hoping the integer division as 0.45 but that is actually 0
Try to change this as:
float CivIndex = ( (45.0/100) - (20.0+50.0)/200 )
*(10+5);
You are essentially evaluating an expression containing only integers. So the
result will be an integer.
You can use casts on the final result of the integer expression.
e.g..
int a=20;float b; b=(float)a;cout<<"b: "<<b;
Please confirm the syntax.
Or as stated above, you can also make one of you operands as a float/double(if your requirement permits).
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.