0

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;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
DJKristy
  • 27
  • 1
  • 4
  • Be aware that double is not precise! Calculations that in mathematics result in exactly 1.6 differ if calculated in double. *Necessarily*, as 1.6 itself cannot be represented exactly in double (1.6 is periodic in binary representation!). All the same for long double as well (solely precision is a bit higher). – Aconcagua Oct 03 '19 at 19:01

3 Answers3

3

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) )
R Sahu
  • 204,454
  • 14
  • 159
  • 270
2

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.

Ruslan
  • 18,162
  • 8
  • 67
  • 136
-3

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) {