100 <= x <= 150 as argument in if (), acting funny - objective-c

I have an if statement followed by several else if statements. All of the if/else if statements have an argument structured something like this:
if (100 <= x <= 149) //do this
else if (150 <= x <= 199) //do that
else if ...etc...
However, for some reason only the first if statement ever gets executed. X can be 200 and only the first if statement will be recognized.
I'm not sure why it isn't moving on to the next else if statement when X doesn't fit the argument of the preceding statement. Does this not work in Obj-C? Any help is appreciated. Thanks

You need to rephrase the statements like:
if (x >= 100 && x <= 149) {
} else if (x >= 150 && x <= 199) {
} ...
Your first if is evaluated like:
if ((100 <= x) <= 149)
Let's have a look how that evaluates:
If x = 200, then (100 <= 200) is true and thus evaluates to the value 1 (which means true). And then 1 <= 149 is also true.
If x has a value smaller than 100, for example 10, then (100 <= 10) is false and thus evaluates to the value 0 (which means false). Again, 0 <= 149 is true.
So regardless of the value of x, the whole expression will always be true.

C is not math, so
if (100 <= x <= 149)
is NOT the same as
if (100 <= x && x <= 149)
Which is what you meant. The former will be true always, because 100 <= x <= 149 becomes
((100 <= x) <= 149)
leaving two possibilities: (1 <= 149) or (0 <= 149). Both are always true.

Chained comparisons like these don't work in C-based languages. Or rather, they do, but not how you'd expect.
100 <= x <= 149 gets evaluated as (100 <= x) <= 149. If x is over 100, then (100 <= x) will evaluate to true, or 1. If x is under 100, it's false, or 0. In either case, 0 <= 149 or 1 <= 149 is true, so the overall expression is true.
To fix this, change your conditions to look like this:
if (100 <= x && x <= 149)
That will make it work as you expect.

The compiler sees an expression formulated from binary operators. The <= symbol is a binary operator, as are =, >=, ||, &&, and so forth.
Just as with arithmetic, there is an order of precedence that the compiler must follow, evaluating the expression formed around each binary operator.
In arithmetic, you are probably familiar with this, as with these two examples:
2+5*7 This evaluates to 2+(5*7) or 37, because multiplication has precedence over addition.
2+3+21 is evaluated in the order the terms are read from left to right, since there is no other precedence rule. It becomes (2+3)+21.
So 100<=x<=150 is an expression of a similar type, where the binary operators are all the same, and thus have the same precedence. Once again, this is resolved by evaluating it from left to right, so it becomes (100<=x)<=150. If x>=100 the term in parentheses evaluates to TRUE, which has a numeric value of 1. Since 1 is less than 150, the rest evaluates to 1<=150, or TRUE, if x is greater than or equal to 100. On the other hand, it also evaluates to TRUE if x is less than 100, because the second comparison becomes 0<=150, which is TRUE.
The other recommendations to break this down with parentheses are correct if you aren't sure of the order of precedence for binary operators: (100<=x) && (x<=150). You can also write it as 100<=x && x<=150 since the order of precedence for value comparisons is higher than for logical operators.

Because if (100 <= x <= 149) is the same as if(1<=149) if you give 200 or another number to x. And that is correct always.
For example.
x=1
100<=1 is false so you get if(0<=149) which is true
x=200
100<=200 is true so you get if(1<=149) which is true
So you always get true for it.
So you must do it in another way, like this
if(x>=100 && x<=149) ...

Adding some additional parenthesis may help.
if ((100 <= x) && (x <= 149)) //do this

I don't think you can write math functions like this in objective-c... Try separating them and combining with an && statement:
if ( (100 <= x) && (x <= 149) ) { // "&&" = and, "||" = or, other math comparison operators are: <=, >=, <, >, ==, != (!= is does not equal))
//do this
} else if ( (150 <= x) && (x <= 199) ) {
//do that
} else if ...etc...

You've already got a lot of answers, but I'll add one more to cover one other possible point of confusion.
In C & Obj-C the boolean (and character) types are treated as integer types, which is not the case in call languages. So expressions like 'z' * true make perfect sense!
(Modern) C uses the type _Bool for boolean, which is defined to be large enough to hold 0 & 1. Cocoa uses the type BOOL for boolean, which is defined as signed char. CoreFoundation uses the type Boolean which is defined as unsigned char. All three define YES/true as 1 and NO/false as 0, while C itself treats any non-zero value as true.
The relation operators such as <, <= etc. are defined to return the int (yes, none of the booleans, not even _Bool) value 0 if the relation is false, and the int value 1 if the relation is true.
Given this and the left-to-right associativity of relational operators your:
if (100 <= x <= 149)
is parsed as:
if ((100 <= x) <= 149)
then 100 <= x evaluates to the int value 1 if x is greater than or equal to 100, otherwise it evaluates to the int value 0, so we get:
if (1 <= 149)
or
if (0 <= 149)
both of these evaluate to 1 so we get:
if (1)
and the if statement branches to the "then" branch if it's expression is non-zero.
It may be surprising, but the whole statement is evaluated without any use of booleans at all - it is all done with integers.
To achieve what you intended you need:
if((100 <= x) && (x <= 149))
etc. - which also doesn't use any booleans (&& is defined in terms of integers).

Related

Conditional Expression for statement

I do not understand the meaning of inclusive in this statement; Sum of X and Y must be between 50 and 100 inclusive. I am currently attempting to write a conditional expression for that statement however I have attempted to write two separate statements. I have written them below;
1.
(((X + Y) > 50) and ((X + Y) < 100))
2.
X + Y = Z
(Z > 50) and (Z < 100)
If X and Y are integers, you could write either of:
If X+Y >= 50 AndAlso X+Y <= 100 Then
...
If X+Y > 49 AndAlso X+Y < 101 Then
...
If X and Y are floating point numbers you're best sticking to the first form
Be careful using And; it's a multipurpose operator that can work as you have here - evaluating the overall truth of test1 AND test2 - but it can also do bitwise operations on numbers, so like 5 And 3 giving a result of 1, and it always evaluates the left and the right before returning a result so if you write If x IsNot Nothing And x.SomeProperty = someValue you'll get a crash. In 99.9% of cases where you're ANDing things, you probably want to use AndAlso instead of And
You can also use a Case statement in VB to quite succinctly test your X+Y for being between 50 and 100:
Select X + Y
Case 50 to 100 'always inclusive
...
End Select
The phrase "inclusive" means "including this value". The opposite is "exclusive".
A range specified as "50 to 100 inclusive" is usually 50,51,...,99,100
A range specified as "50 to 100 exclusive" is usually 51,52,...,98,99
A range might also be specified as "50 inclusive to 100 exclusive" (50,51,...,98,99) or similarly "50 exclusive to 100 inclusive" (51,52,...,99,100)

VBA policy on double sided inequalities?

Was fooling around with trying to reduce the length of the code so that it gives off fewer headaches to look at and debug, and I came across this curious little fact:
Debug.Print 5<9<8 'returns "True"
At first I thought this was because it just checked the first set, but then I found that
Debug.Print 5<4<8 '*also* returns "True"
Does VBA interpret this kind of triple inequality as an Or statement? I can't imagine why someone would choose to make that the interpretation VBA makes because it's almost certainly the less used option, but I struggle to think of another explanation.
Also, what is a quick and pretty way of writing If 5 < X < 8 Then (to use sample numbers), without having to resort to endless And statements, ie If 5 < x And X < 8 Then? It's okay for one statement, but the doubling of length adds up quick, especially since variables aren't typically named X.
Edit: okay, it's certainly not an Or because VBA also says that Debug.Print 8<6<2 is True. What on earth is it thinking?
I have no clue but my educated guess would be that it first evaluates the left side of the equation (5<9) which gives TRUE. Then, it proceeds to evaluate the rest (TRUE<8) and implicitly converts TRUE to its integer value (I believe this to be -1 in VB).
-1<8 -> TRUE
Works with the second case as well since FALSE will convert to 0 and 0<8.
Basically it would have everything to do with implicit conversion of boolean to integer and their respective value in VBA.
It's to do with the way VBA evaluates expressions and implicit conversion. The first part of the equation is evaluated and the result stored as a numeric value (the boolean is implicitly converted to an integer)
(well.... technically a boolean is just an integer, but we'll just go along like so...)
'// True = -1
'// False = 0
Debug.Print 5 < 9 < 8
Debug.Print CInt(5 < 9) '// Prints -1
Debug.Print -1 < 8 '// = True
Which is why the following gives "False" instead:
Debug.Print 5 < 9 < -1
Because
Debug.Print Cint(5 < 9) '// True = -1
Debug.Print -1 < -1 '// False
If you want to find out if something is in the middle of two other numbers then you have to use the And operator to force a separate evaluation (either side of the operator is then evaluated and compared logically)
Debug.Print (3 < 5 And 5 < 4) '// False
Looking at it from a parse tree perspective might shed more light about why it works that way.
Excluding whatever instruction comes after the THEN token, the parse tree for If 5 < X < 8 Then might look something like this (quite simplified):
The comparison operators being a binary operator, there's an expression on either side of it, and in order to resolve the Boolean expression for the IfBlockStatement, VBA needs to visit the tree nodes in a specific order: because VBA parses expressions left to right, the 5 < X part stands on its own as an expression, and then the result of that expression is used to resolve the {expression} < 8 part of the expression.
So when VBA resolves 5 < X, because that's a ComparisonExpression the result is a Boolean value; when that Boolean value then needs to be compared to the 8 integer literal, VBA performs an implicit type conversion and actually compares CInt({Boolean}) < 8, which will evaluate to True regardless of the result of the first expression, since False converts to 0 and True converts to -1 when expressed as an integer literal, and both are < 8.
These mechanics are built into how the runtime works, so in order to evaluate if X is between 5 and 8, you need to build your expression so that it's parsed as such:
If X > 5 And X < 8 Then
That gives you two distinct expression trees joined by a LogicalAndOperator, which then works off a valid Boolean expression on either sides.
5<9<8 = True<8 = True
5<4<8 = False<8 = True
The other answers covered up nicely the first part of your question, but didn't satisfactorily cover up the second part of it, i.e. What is a quick and pretty way of writing If 5 < X < 8 Then (to use sample numbers), without having to resort to endless And statements, i.e. If 5 < x And X < 8 Then?
There are two ways. The first:
Select Case X
Case 5 To 8
...
End Select
Here, the value before the To keyword must be the smaller value of the two. Also note that while this will work for integers, I have no idea if it works for types like Double and such (I suspect it won't though).
The second way, which works irrespective of whether the interval bounds are integers or not, is not necessarily shorter, but it evaluates things in a single comparison:
If Sgn(x - 5) + Sgn(x - 8) = 0 Then ...
This is an interesting way of evaluating whether a value is between some bounds, because it can also provide information on whether the value is equal to one of those bounds or is "outside" them (and on which "side" it is). For example, on a -∞..0..+∞ axis:
if x = 4, the expression above is -2, thus x is to the left of the (5..8) interval
if x = 5, the expression above is -1, thus x is the left bound of the (5..8) interval
if x = 6, the expression above is  0, thus x is inside the (5..8) interval, i.e. between its bounds
if x = 8, the expression above is  1, thus x is the right bound of the (5..8) interval
if x = 9, the expression above is  2, thus x is to the right of the (5..8) interval
Of course, if you want to include the bounds in the interval, say, test If 5 <= x And X <= 8 Then, the comparison above becomes If Abs(Sgn(x - 5) + Sgn(x - 8)) < 2 Then ..., which is another shortcut to check if the expression is -1, 0 or 1.
In the end, none of the ways above are as short as a Between(x, 5, 8) hypothetical function, but at least they are alternatives to the "classical" method.

What is the difference between == and <= in this case

I was working on making a game, and I was wondering why the construct with the == operator doesn't work while the lower one does. I used an NSLog message afterwards to test.
if (pipe.position.x == bird.position.x){ no idea why this doesn't work
if ((pipe.position.x <= bird.position.x) & (pipe.position.x > bird.position.x - 1)){
This is because one (or both) of the position.x's are a floating-point2 value with a non-zero difference1 between the two position values such that only the second condition is true.
Since p <= b is true for all values that make p == b true, to see why this works "unexpectedly" let's choose some values such that the expression p == b is false2 yet p < b is true and p > b - 1 is true.
Given p = 3.2 (pipe) and b = 3.7 (bird), as an example, then
p == b
-> 3.2 == 3.7
-> false
but
(p <= b) & (p > b - 1)
-> (3.2 <= 3.7) & (3.2 > 3.7 - 1)
-> (3.2 <= 3.7) & (3.2 > 2.7)
-> true & true
-> true
Instead, to detect when the bird "is crossing" the pipe, assuming that x increases to the right, consider
// The bird's head to the "right" of the pipe leading edge..
bird_x >= pipe_x
// ..but bird's butt is not to the "right" of the pipe trailing edge.
// (Also note use of the &&, the logical-AND operator)
&& (bird_x - bird_width <= pipe_x + pipe_width)
Of course, using a non-rectangle (or forgiving overlap) collision detection would lead to less frustrating flapping!
1 This issue occurs because there are some particular floating-point values (but there are no integer values) which can cause the observed effect.
First, reiterate the assumption that p is not equal to b, given that the first condition does not succeed. Let's suppose then that p <= b is written as p == b || p < b but since p == b is false , we can write it as p < b by tautology.
Since both clauses in the second condition are true (such that true && true -> true), we have the rules: 1) p < b is true, and 2) p > b - 1 is true.
Rewriting p < b as p - b < 0 and p > b - 1 as p - b > -1, and then replacing p - b with x yields: x < 0 and x > -1. However, there is no integer value of x which satisfies -1 < x < 0.
(In first section, where p = 3.2 and b = 3.7, x = (p - b) = 0.5 which satisfies the given constraints when x is not restricted to an integer value.)
2 With all above aside, it is possible for p and b to be "very close but different" floating-point values such that there is a non-zero difference between them - due to rounding, they may even be displayed as the same integer value! See How dangerous is it to compare floating point values? and related questions for the cause and "odd" behavior of such when using ==.
If this is the case then round to integer values and use an integer comparison, or; rely entirely on relational comparison such as shown in the proposed condition, or; use epsilon comparison for "nearly equal" of floating-point values.
if you choose abs(pipe.position.x) == abs(bird.position.x) the first condition may satisfy.

Not Equal to This OR That in Lua

I am trying to verify that a variable is NOT equal to either this or that. I tried using the following codes, but neither works:
if x ~=(0 or 1) then
print( "X must be equal to 1 or 0" )
return
end
if x ~= 0 or 1 then
print( "X must be equal to 1 or 0" )
return
end
Is there a way to do this?
Your problem stems from a misunderstanding of the or operator that is common to people learning programming languages like this. Yes, your immediate problem can be solved by writing x ~= 0 and x ~= 1, but I'll go into a little more detail about why your attempted solution doesn't work.
When you read x ~=(0 or 1) or x ~= 0 or 1 it's natural to parse this as you would the sentence "x is not equal to zero or one". In the ordinary understanding of that statement, "x" is the subject, "is not equal to" is the predicate or verb phrase, and "zero or one" is the object, a set of possibilities joined by a conjunction. You apply the subject with the verb to each item in the set.
However, Lua does not parse this based on the rules of English grammar, it parses it in binary comparisons of two elements based on its order of operations. Each operator has a precedence which determines the order in which it will be evaluated. or has a lower precedence than ~=, just as addition in mathematics has a lower precedence than multiplication. Everything has a lower precedence than parentheses.
As a result, when evaluating x ~=(0 or 1), the interpreter will first compute 0 or 1 (because of the parentheses) and then x ~= the result of the first computation, and in the second example, it will compute x ~= 0 and then apply the result of that computation to or 1.
The logical operator or "returns its first argument if this value is different from nil and false; otherwise, or returns its second argument". The relational operator ~= is the inverse of the equality operator ==; it returns true if its arguments are different types (x is a number, right?), and otherwise compares its arguments normally.
Using these rules, x ~=(0 or 1) will decompose to x ~= 0 (after applying the or operator) and this will return 'true' if x is anything other than 0, including 1, which is undesirable. The other form, x ~= 0 or 1 will first evaluate x ~= 0 (which may return true or false, depending on the value of x). Then, it will decompose to one of false or 1 or true or 1. In the first case, the statement will return 1, and in the second case, the statement will return true. Because control structures in Lua only consider nil and false to be false, and anything else to be true, this will always enter the if statement, which is not what you want either.
There is no way that you can use binary operators like those provided in programming languages to compare a single variable to a list of values. Instead, you need to compare the variable to each value one by one. There are a few ways to do this. The simplest way is to use De Morgan's laws to express the statement 'not one or zero' (which can't be evaluated with binary operators) as 'not one and not zero', which can trivially be written with binary operators:
if x ~= 1 and x ~= 0 then
print( "X must be equal to 1 or 0" )
return
end
Alternatively, you can use a loop to check these values:
local x_is_ok = false
for i = 0,1 do
if x == i then
x_is_ok = true
end
end
if not x_is_ok then
print( "X must be equal to 1 or 0" )
return
end
Finally, you could use relational operators to check a range and then test that x was an integer in the range (you don't want 0.5, right?)
if not (x >= 0 and x <= 1 and math.floor(x) == x) then
print( "X must be equal to 1 or 0" )
return
end
Note that I wrote x >= 0 and x <= 1. If you understood the above explanation, you should now be able to explain why I didn't write 0 <= x <= 1, and what this erroneous expression would return!
For testing only two values, I'd personally do this:
if x ~= 0 and x ~= 1 then
print( "X must be equal to 1 or 0" )
return
end
If you need to test against more than two values, I'd stuff your choices in a table acting like a set, like so:
choices = {[0]=true, [1]=true, [3]=true, [5]=true, [7]=true, [11]=true}
if not choices[x] then
print("x must be in the first six prime numbers")
return
end
x ~= 0 or 1 is the same as ((x ~= 0) or 1)
x ~=(0 or 1) is the same as (x ~= 0).
try something like this instead.
function isNot0Or1(x)
return (x ~= 0 and x ~= 1)
end
print( isNot0Or1(-1) == true )
print( isNot0Or1(0) == false )
print( isNot0Or1(1) == false )

Conditional statement in Objective C with two comparison operators in a single clause

I've been learning Objective C lately, and I came across some code for using the accelerometer in an iPhone app. It works perfectly; however, there's one if-statement in the code which I simply cannot understand (both the meaning and why it works). The specific chunk is this:
if (0.2f < deviceTilt.y > -0.2f){position.x = 0;}
I just can't figure out the condition, and I hadn't seen the use of two comparison operators in one single clause before.
Hope somebody can help me out!
PS: The whole project can be found in this link: http://www.ifans.com/forums/showthread.php?t=151394
This is evaluated like:
let y := .1
if ((.2 < y) > -.2)
if (false > -.2)
false is treated as an int
if (0 > -.2)
if (true)
let y := .3
if ((.2 < y) > -.2)
if (true > -.2)
true is treated as an int
if (1 > -.2)
if (true)
-> always true
most likely this was meant:
if ((.2 < y) && (y > -.2))
This is certainly atypical and most people wouldn't like it. To really understand what is going on, you have to understand C's operator precedence. See: http://www.swansontec.com/sopc.html.
Let's analyze the statement knowing that conditionals associate left-to-right:
1) 0.2f < deviceTilt.y. This is either true (which is 1) or false (which is 0)
2) The result of (1) > -0.2f. Which should always be true.
So this is the same as if(1) or always true