Equalities in C/C++ - c++

In C++, the usual way of determining if some value, x, is between two limits is to:
//This is (A)
double x = 0.0d;
double lower = -1.0d;
double upper = +1.0d;
if(x > lower && x < upper){
// Do some stuff
}
But today I discovered by accident that I can do this:
// This is (B)
double x = 0.0d;
double lower = -1.0d;
double upper = +1.0d;
if(lower < x < upper){
// Do some stuff
}
It seems to work fine, but I've never heard of this being done before, with "lower < x < upper". Does this produce executable code as you would expect it to? IE, is (A) equivalent to (B)?
I think a lot of people won't know about this, and I suspect that might be because the compiler interprets (A) differently to (B). It this right?

No, A and B are not equivalent, you cannot do this.
Or, obviously you can (as you discovered) but you're not doing what you think you're doing.
You're evaluating (lower < x) < upper, i.e. the value of lower < x (which is false or true, but which convert to int for the comparison) is compared to upper.
See this table of operator precedence for more information.

They are definitely not equivalent. Your expression lower < x < upper will first evaluate lower < x to either true or false, and then do true < x or false < x respectively.

It doesn't work fine. In fact, it's dead wrong, and only works by accident.
lower < x < upper is parsed as (lower < x) < upper; (lower < x) has type bool, and its value is either true or false, depending on the value of x. To compare that bool value to upper the compiler converts the bool to a float with the value 1.0 for true and 0.0 for false.

Well, yes. In either cases x is between the value range.
For example:
lower = 4;
upper = 9;
x = 7;
If you do: 7 > 4 && 7 < 9 is the same as saying 4 < 7 < 9.
This is basic arithmetics, by the way.

Related

Incorrect variable range behavior in RooFit

The RooFit package allows me to import some TTree branches, but it constrains values included in those branches between the min and max value set by a RooRealVar. For instance:
RooRealVar t1("t1", "Some variable", 0.0, 1.0);
RooDataSet data("data", "My Dataset", RooArgSet(t1), Import(*myttree));
so long as the TTree myttree contains a branch called t1. This is all fine and good, until you start getting close to floating point values in the range. My particular problem occurs because I have a variable like t1 which maps to some variable with an exponential distribution. I'm trying to fit this distribution, but the fits fail for values of t1 ~ 0.0. My solution was to just change the range a bit to cut off potential events where the stored value of t1 in the tree is actually zero or close to it (all the following code is run in the ROOT interpreter, but I have confirmed it works in compiled code as well):
root[0] RooRealVar t1("t1", "Some variable", 0.001, 1.0);
However, note the following annoying behavior:
root[1] t1 = 0.000998;
root[2] t1.getVal();
(double) 0.0010000000
// this is correct, as 0.000998 < 0.001 so RooFit set it as the lower limit
root[3] t1 = 0.000999;
root[4] t1.getVal();
(double) 0.00099900000
// this is incorrect.
Yes, the extra zero is printed in the second case, which I also don't understand, but I'm mostly concerned with the failure to recognize that 0.000999 < 0.001. When I compare these values later in an if-statement, I find that C++ can tell the difference. Everything appears to be double precision here, and I've been tracing through the code to see where the precision error seems to crop up. Correct me if I'm wrong, but a float should still hold these numbers up to comparison precision, right? What's going on here? If this is some floating point error problem, what's the best way to resolve it? I have several events with values like t1 = 0.000999874, and changing the bounds to something like 0.0001 doesn't really help either, there are still events which live on this edge.
Edit: I want to emphasize that while this is probably a floating point problem, it really shouldn't be. For instance, the following code works:
root[0] RooRealVar t1("t1", "Some variable", 0.001, 1.0);
root[1] t1 = 0.000999;
root[2] t1.getVal() < 0.001;
(bool) true
Well everyone, I found the answer (and I hate it). It actually has very little to do with floating point arithmetic, and I'm honestly not sure why the code was written this way. From the source code that determines if a value is "in range":
bool RooAbsRealLValue::inRange(double value, const char* rangeName, double* clippedValPtr) const
{
// double range = getMax() - getMin() ; // ok for +/-INIFINITY
double clippedValue(value);
bool isInRange(true) ;
const RooAbsBinning& binning = getBinning(rangeName) ;
double min = binning.lowBound() ;
double max = binning.highBound() ;
// test this value against our upper fit limit
if(!RooNumber::isInfinite(max) && value > (max+1e-6)) {
clippedValue = max;
isInRange = false ;
}
// test this value against our lower fit limit
if(!RooNumber::isInfinite(min) && value < min-1e-6) {
clippedValue = min ;
isInRange = false ;
}
if (clippedValPtr) *clippedValPtr=clippedValue ;
return isInRange ;
}
As we can see here, RooFit doesn't actually check if min < val < max or even min <= val <= max but rather min - 1e-6 < value < max + 1e-6! I couldn't find a single place where this was documented explicitly, but I'm even more concerned that there is a separate implementation of inRange which takes a variable name (or comma separated list of variable names) and returns a result which is incompatible with the prior implementation:
bool RooAbsRealLValue::inRange(const char* name) const
{
const double val = getVal() ;
const double epsilon = 1e-8 * fabs(val) ;
if (!name || name[0] == '\0') {
const auto minMax = getRange(nullptr);
return minMax.first - epsilon <= val && val <= minMax.second + epsilon;
}
const auto& ranges = ROOT::Split(name, ",");
return std::any_of(ranges.begin(), ranges.end(), [val,epsilon,this](const std::string& range){
const auto minMax = this->getRange(range.c_str());
return minMax.first - epsilon <= val && val <= minMax.second + epsilon;
});
}
Here, we can see the creation of an epsilon = 1e-8 * fabs(val) rather than the arbitrary 1e-6 given in the first definition. This comparison uses a <= rather than a < also. It should be noted that the method used to filter trees when imported in this way uses the first implementation (source here).
Somewhere along the way (I'm not entirely sure where actually), some of these arbitrary comparisons lead to the following paradoxical behavior:
root[0] RooRealVar t1("t1", "Some variable", 0.001, 1.0);
root[1] t1 = 0.001 - 1e-6;
(RooAbsArg &) RooRealVar::t1 = 0.000999 L(0.001 - 1)
root[2] t1 = 0.001 - 1e-8 * 0.001;
(RooAbsArg &) RooRealVar::t1 = 0.001 L(0.001 - 1)
root[3] t1 = 0.00099999999;
(RooAbsArg &) RooRealVar::t1 = 0.001 L(0.001 - 1)
I would classify this as a bug. Under no circumstances should 0.00099900000 be classified as within the range of (0.001 - 1) where 0.00099999999 is not!

Linear Programming: Depict logical expression in a boolean variable

I have a mixed integer linear program (MIP or MILP).
In the end I want a boolean variable im my linear program, that has the following properties.
I have two variables:
boolean b.
real x, with x being 0 or larger.
What I want to achieve is:
b == false if x == 0.
b == true if x > 0.
I found a way to depict if x is in specific range (e.g. between 2 and 3) via:
2*b <= x
x <= 3*b
The problem with the above testing formula is, that b will be true if x is in the given range and false if outside that range.
Does anybody know a way to set a boolean variable to false if x == 0 and to true if x is larger than 0?
If U is an upper bound of x then
if x > 0 ==> b == 1
can be made as
x <= U*b
The second part (x == 0 => b == 0) needs to be modified to
x < epsilon ==> b == 0
which can be made as
b <= 1 + x - epsilon
where epsilon is a small number. Other than good practice this is necessary, because solvers do not work in rational arithmetic (although there are some research efforts to make them do so), but with certain precision thresholds, and therefore quantities such as 10e-12 are treated as zero.
I hope this helps!
You could use the signum function http://en.wikipedia.org/wiki/Signum_function take the absolute value and negate it. Since you didn't name a specific programming language I keep it general.

What is the difference between ! ( x < y ) and x >= y in C++?

Going through EASTL, I stumbled across a peculiar line of code. The following link shows the file with the line number of interest at 1870.
https://github.com/paulhodge/EASTL/blob/master/include/EASTL/algorithm.h
The code at that line is if(!(value < *i)). The comment says that "we always express value comparisons in terms of < or ==" without any explanation as to why this is so. There are also a few other areas where the same comment is placed but without any explanation.
Is there any benefit whatsoever to writing a comparison like that (maybe some context that I am overlooking)? If not, why did the author of EASTL deliberately wrote it in this particular fashion and even took the care to comment about it? Is consistency the only reason here?
It means you only need to provide < and == for container value types. It also means you reduce the amount of variability for those types (as all the algorithms use !(a<b) to mean a>=b and !(a==b) for a!=b); otherwise, you could have >= and != return inconsistent results.
In C++, you can overload the < operator so that it behaves differently than the opposite of >=, so they are not guaranteed to be equivalent.
Additionally, in any IEEE floating-point implementation, NaN < NaN is false, but so is NaN >= NaN, so !(NaN < NaN) is true even though NaN >= NaN is false.
I see at least one difference. If one of the numbers was QNAN (floating-point 0/0) then !(a < b) would've always return TRUE if any of a or b were QNAN, while it would've always returned false for a>=b
Using just the less-than operator, you can simulate all the other comparison operators. This makes it more consistent and allows you to use a single template parameter when you need to parameterize the comparison. The standard sorted containers and algorithms use std::less<T> as the default template comparator for example.
operation equivalent
x < y x < y
x > y y < x
x <= y !(y < x)
x >= y !(x < y)
x == y !(x < y) && !(y < x)
x != y (x < y) || (y < x)
For those operations where ordering is not important it's simpler and more efficient to use operator == instead.

Unexpected output of C code

What would be the output of this program ?
#include<stdio.h>
#include<conio.h>
void main()
{
clrscr();
int x=20,y=30,z=10;
int i=x<y<z;
printf("%d",i);
getch();
}
Actually i=20<30<10, so the condition is false and the value of i should be 0 but i equals 1. Why?
This int i=x<y<z; doesn't work the way you intended.
The effect is int i=(x<y)<z;, where x<yis evaluated first, and the value true is then compared to z.
Pascal points out below that in C the result of the comparison is 1 instead of true. However, the C++ true is implicitly converted to 1 in the next comparison, so the result is the same.
The comparison operators don't work like that. Your program is equivalent to:
i = (x < y) < z;
which is equivalent to:
i = (x < y);
i = i < z;
After the first operation, i == 1. So the second operation is equivalent to:
i = 1 < 10;
You need to rewrite your statement as:
i = (x < y) && (y < z);
The < operator has left-to-right associativity. Therefore x<y<z will do (x<y)<z. The result of the first parenthesis is 1, 1 is smaller than 10, so you'll get 1.
That's not how it works. It's better to see with parenthesis:
int i = (x<y)<z;
Now, first x<y is evaluated. It's true, 20<30, and true is 1 as an integer. 1<z is then true again.
Its precedence is from left to right. Thats is why it is like
20<30 = true
1<10 TRUE
SO FINALLY TRUE
Actually < is left-associative, so first, 20<30 is evaluated (giving 1 usually), then 1 is less than 10.
The output of "1" is correct. This is evaluated as (20<30) < 10, which is 1 < 10, which is 1.
The problem is that you are comparing a boolean value to an integer value which in most cases doesn't make sense.
< is evaulated from left to right, so 20<30 is true, or one, which is less than 10.
The operator < associates from left to right.
So x < y < z is same as ( x < y ) < z
Your expression evaluates as:
( x < y ) < z
= ( 20 < 30 ) < 10
= ( 1 ) < 10
= 1

Turn while loop into math equation?

I have two simple while loops in my program that I feel ought to be math equations, but I'm struggling to convert them:
float a = someValue;
int b = someOtherValue;
int c = 0;
while (a <= -b / 2) {
c--;
a += b;
}
while (a >= b / 2) {
c++;
a -= b;
}
This code works as-is, but I feel it could be simplified into math equations. The idea here being that this code is taking an offset (someValue) and adjusting a coordinate (c) to minimize the distance from the center of a tile (of size someOtherValue). Any help would be appreciated.
It can be proved that the following is correct:
c = floor((a+b/2)/b)
a = a - c*b
Note that floor means round down, towards negative infinity: not towards 0. (E.g. floor(-3.1)=-4. The floor() library functions will do this; just be sure not to just cast to int, which will usually round towards 0 instead.)
Presumably b is strictly positive, because otherwise neither loop will never terminate: adding b will not make a larger and subtracting b will not make a smaller. With that assumption, we can prove that the above code works. (And paranoidgeek's code is also almost correct, except that it uses a cast to int instead of floor.)
Clever way of proving it:
The code adds or subtracts multiples of b from a until a is in [-b/2,b/2), which you can view as adding or subtracting integers from a/b until a/b is in [-1/2,1/2), i.e. until (a/b+1/2) (call it x) is in [0,1). As you are only changing it by integers, the value of x does not change mod 1, i.e. it goes to its remainder mod 1, which is x-floor(x). So the effective number of subtractions you make (which is c) is floor(x).
Tedious way of proving it:
At the end of the first loop, the value of c is the negative of the number of times the loop runs, i.e.:
0 if: a > -b/2 <=> a+b/2 > 0
-1 if: -b/2 ≥ a > -3b/2 <=> 0 ≥ a+b/2 > -b <=> 0 ≥ x > -1
-2 if: -3b/2 ≥ a > -5b/2 <=> -b ≥ a+b/2 > -2b <=> -1 ≥ x > -2 etc.,
where x = (a+b/2)/b, so c is: 0 if x>0 and "ceiling(x)-1" otherwise. If the first loop ran at all, then it was ≤ -b/2 just before the last time the loop was executed, so it is ≤ -b/2+b now, i.e. ≤ b/2. According as whether it is exactly b/2 or not (i.e., whether x when you started was exactly a non-positive integer or not), the second loop runs exactly 1 time or 0, and c is either ceiling(x) or ceiling(x)-1. So that solves it for the case when the first loop did run.
If the first loop didn't run, then the value of c at the end of the second loop is:
0 if: a < b/2 <=> a-b/2 < 0
1 if: b/2 ≤ a < 3b/2 <=> 0 ≤ a-b/2 < b <=> 0 ≤ y < 1
2 if: 3b/2 ≤ a < 5b/2 <=> b ≤ a-b/2 < 2b <=> 1 ≤ y < 2, etc.,
where y = (a-b/2)/b, so c is: 0 if y<0 and 1+floor(y) otherwise. [And a now is certainly < b/2 and ≥ -b/2.]
So you can write an expression for c as:
x = (a+b/2)/b
y = (a-b/2)/b
c = (x≤0)*(ceiling(x) - 1 + (x is integer))
+(y≥0)*(1 + floor(y))
Of course, next you notice that (ceiling(x)-1+(x is integer)) is same as floor(x+1)-1 which is floor(x), and that y is actually x-1, so (1+floor(y))=floor(x), and as for the conditionals:
when x≤0, it cannot be that (y≥0), so c is just the first term which is floor(x),
when 0 < x < 1, neither of the conditions holds, so c is 0,
when 1 ≤ x, then only 0≤y, so c is just the second term which is floor(x) again.
So c = floor(x) in all cases.
c = (int)((a - (b / 2)) / b + 1);
a -= c * b;
Test case at http://pastebin.com/m1034e639
I think you want something like this:
c = ((int) a + b / 2 * sign(a)) / b
That should match your loops except for certain cases where b is odd because the range from -b/2 to b/2 is smaller than b when b is odd.
Assuming b is positive, abs(c) = floor((abs(a) - b/2) / b). Then, apply sign of a to c.