Double inequality while comparying three floating point numbers [duplicate] - c++

This question already has answers here:
Comparing a variable to a range of values
(7 answers)
Why can't we do three-way comparison in C++? [duplicate]
(6 answers)
Closed 1 year ago.
Can somebody tell me why the following does not work?(I mean no output)
if(0.0001<0.001<0.01)
cout<<"hi\n"<<endl;
output: (blank)
While the following works:
if(0.0001<0.001 && 0.001<0.01)
cout<<"hi\n"<<endl;
output:hi

Because there is no magical n-ary < operator in C++.
0.0001 < 0.001 < 0.01
is parsed (since < is left-associative) as
(0.0001 < 0.001) < 0.01
and 0.0001 < 0.001 returns a value of type bool with value true. Now you have
true < 0.01
but according to the standard a true boolean has value 1 when converted to an integral type so you have
1 < 0.01
which is false.

If you mean simply you don't understand what 0.0001<0.001<0.01 means or why it doesn't evaluate to what you expect: C++ only defines binary versions of the comparison operators. So 0.0001 < 0.001 < 0.01 is not a single comparison of all three values; it's a comparison of two values and then another comparison of the third value with the result of the other comparison. I.e. 0.0001 < 0.001 < 0.01 is the same as (0.0001 < 0.001) < 0.01 is the same as true < 0.01 is the same as 1 < 0.01
If you mean why didn't C++ define operators to work the way you want here, it's because nobody saw enough value in making C++ work that way.

When you are using condition like
(0.0001<0.001<0.01)
It will check first 0.0001<0.001 i.e. true which returns 1 and now condition become
( 1< 0.01 )
which is false so returns 0 that's why printing nothing.

Related

Dividing two numbers inside an if statement gives wrong output [duplicate]

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

If statement without '&&' works? [duplicate]

This question already has answers here:
Comparing a variable to a range of values
(7 answers)
Closed 3 years ago.
int n = 5;
if(2<=n<=20)
{
cout << "hello";
}
In the above code, it does not give an error, it runs successfully and gives "hello" as output.
But we have to use && in this kind of equation.
Can anyone explain this?
<= is left-associative in C++, so the expresion is parsed as ((2 <= n) <= 20). 2 <= n is of type bool, which can implicitly convert to int: true converts to 1 and false converts to 0.
Both of these are <= 20, so the condition is effectively always true.
Note that the above assumes n is an int or another primitive numerical type. If n is a user-defined class with operator <= overloaded, the associativity bit is still true, but the part about implicit conversions may or may not apply, based on the return type and semantics of that overloaded operator.
2<=n<=20 will be executed as (2<=n)<=20.
2<=n results in 0 or 1, depending on the value of n.
0<=20 and 1<=20 are true, so the cout will be executed, independent of the value and type of n.
n could be an object of a class with overloaded operators where 2<=n results to something (object to a class or a value >21), which compared with <=20 results to false. In this case there would be no output.
You probably mean
if (2 <= n && n <= 20)
C++ and C group 2 <= n <= 20 as (2 <= n) <= 20; the sub-expression is either 0 (false in C++) or 1 (true), which are both less than or equal to 20, hence the entire expresion is 1 (true). This is true for any primitive non-pointer type n, including a floating point NaN.
The first comparison 2 <= n is evaluated first. This returns true, which is convertible to an int. From conv.integral#2:
If the source type is bool, the value false is converted to zero and the value true is converted to one.
Once true is converted to 1 or 0, the next comparison is 1 <= 20 or 0 <= 20 which is always true. Hence the output.

Calculation returns zero instead of expected result [duplicate]

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

math.h pow() function not working correctly?

I was working on a personal project in which I needed to determine all prime powers between 0 and 999. Because I am not particularly good at math, I tired the following ham-fisted bruteforce approach.
bool constexpr is_prime(int imp)
{
return imp == 1 ? false : (imp % imp == 0 && imp % 1 == 0 && [&imp]{ for(int i = 2; i < imp; ++i) if(imp % i == 0) return false; return true;}());
}
bool is_prime_power(int imp)
{
for(int i = 1; i < 1000; ++i)
if (is_prime(i))
for (int j = 0; j < 100; ++j)
if (imp == pow(i, j))
return true;
return false;
}
For 0...30 the output should be (according to A000961):
1 2 3 4 5 7 8 9 11 13 16 17 19
However, this is what I get instead:
1 2 3 4 5 7 8 9 11 16 19
Where did 13 and 17 vanish to?
Since I could not find any logical problems with my approach I implemented my own pow() function.
double constexpr _pow(double base, double exp)
{
return exp == 0 ? 1 : base*pow(base, exp - 1);
}
Now if I call my version of _pow() instead of pow() from math.h the output is displayed as excepted. Is my implementation wrong? If not, pow() from math.h can't be working correctly.
Any idea what is causing this?
The problem is that double (and floating-point numbers in general) aren't exact and the math functions in the standard library also use approximate formulae to do the calculations. If you call pow(2, 10), you may get 1023.999375, for example (which is then, depending on the context, may be truncated down to 1023).
So, instead of using the floating-point pow() function from the standard library, you can go with your own, exact implementation for integers:
int constexpr _pow(int base, int exp)
{
return exp == 0 ? 1 : base * _pow(base, exp - 1);
}
(or change it to whatever integral type you want if you need unsigned or long long).
You never need to verify that a number divides itself and that one divides a number. This is useless: imp % imp == 0 && imp % 1 == 0
Otherwise the problem you have is because pow returns a double or float while you compare it to an integer. The comaparison may fail because of the rounding error. I would suggest you implement your own integer power operation so that you avoid any rounding error. Alternatively convert i to double and use comparison with some small epsylon tolerance.

Condition in "if" ignored in "for" loop

For below code, when input is:
first input = 0 1 2 3 4 5 6 7 8 9
second input = 1 2 3 4 5 6 7 8 9 10
it will produce output of:
first output = 0
second output = 1
instead of taking each input quartile it take its first element, and the problem is (after testing and such), it follow with the problem in code
for (vector<int>::size_type counter = 0; (quartiles < quadro) && (counter < numstore.size()); ++counter)
{
if (counter == (quartiles/quadro * numstore.size()))
{
quaele.push_back(numstore[counter]);
if ((quartiles == 2) && (numstore.size() / 2 == 0))
quaele[quartiles-1] = (numstore[counter]+numstore[counter-1]) / 2;
++quartiles;
}
// test
cout << quartiles;
}
where the conditional in "if function" doesn't work, I mean on first loop, counter == 0, how can 0 == 1(quartiles)/4(quadro) * 10(numstore.size()??
Because quartiles and quadro are both integers and the first is always less than the second (because that's what the for statement says), the expression:
quartiles / quadro * numstore.size()
will always be equal to zero, because quartiles / quadro is calculated first. Hence, the if statement will only ever be true the first time through the loop.
You may be able to get around this by re-arranging the calculation:
quartiles * numstore.size() / quadro
That's how integer arithmetic works. 1/4 is truncated to zero.
You can get the correct result (rounded down to the nearest integer) by multiplying first:
(quartiles * numstore.size()) / quadro
I've used parentheses to make the evaluation order clear - you could leave them out if you prefer.
Note that, for large values, you'll need to be careful that the multiplication doesn't overflow - perhaps by converting to a wider type, or to floating point, or by carefully multiplying and dividing by smaller factors. That is probably not an issue in this case.
The expression quartiles/quadro * numstore.size() will be 0 for the case where quartiles = 1 and quadro = 4. This is because 1/4 is rounded downwards to 0.
Maybe this is what you mean: (quartiles * numstore.size()) / quadro
In C++, the division operator can be thought of as two different operators: one that works on integer operands, and one that works on floating point operands. If the operands are of a floating point type, the division operator will return a floating point value.
http://www.learncpp.com/cpp-programming/eight-c-programming-mistakes-the-compiler-wont-catch/
Try:
float result = quartiles/quadro * numstore.size();
edit: correcting thanks to the comments.
float result = quartiles/(float)quadro * numstore.size();
It is enough to convert one of the operands to a floating point number.
quartiles/quadro is equal to 0.25 and because quartiles is type int quartiles/quadro == 0
In C++ when you divide two integer, you get integer division. Moreover, * and / have the same precedence, so the parser interprets it as (quartiles / quadro) * numstore.size(). And (1 / 4) is equal to 0.