I have recently sat a computing exam in university in which we were never taught beforehand about the modulus function or any other check for odd/even function and we have no access to external documentation except our previous lecture notes. Is it possible to do this without these and how?
Bitwise AND (&)
Extract the last bit of the number using the bitwise AND operator. If the last bit is 1, then it's odd, else it's even. This is the simplest and most efficient way of testing it. Examples in some languages:
C / C++ / C#
bool is_even(int value) {
return (value & 1) == 0;
}
Java
public static boolean is_even(int value) {
return (value & 1) == 0;
}
Python
def is_even(value):
return (value & 1) == 0
I assume this is only for integer numbers as the concept of odd/even eludes me for floating point values.
For these integer numbers, the check of the Least Significant Bit (LSB) as proposed by Rotem is the most straightforward method, but there are many other ways to accomplish that.
For example, you could use the integer division operation as a test. This is one of the most basic operation which is implemented in virtually every platform. The result of an integer division is always another integer. For example:
>> x = int64( 13 ) ;
>> x / 2
ans =
7
Here I cast the value 13 as a int64 to make sure MATLAB treats the number as an integer instead of double data type.
Also here the result is actually rounded towards infinity to the next integral value. This is MATLAB specific implementation, other platform might round down but it does not matter for us as the only behavior we look for is the rounding, whichever way it goes. The rounding allow us to define the following behavior:
If a number is even: Dividing it by 2 will produce an exact result, such that if we multiply this result by 2, we obtain the original number.
If a number is odd: Dividing it by 2 will result in a rounded result, such that multiplying it by 2 will yield a different number than the original input.
Now you have the logic worked out, the code is pretty straightforward:
%% sample input
x = int64(42) ;
y = int64(43) ;
%% define the checking function
% uses only multiplication and division operator, no high level function
is_even = #(x) int64(x) == (int64(x)/2)*2 ;
And obvisouly, this will yield:
>> is_even(x)
ans =
1
>> is_even(y)
ans =
0
I found out from a fellow student how to solve this simplistically with maths instead of functions.
Using (-1)^n :
If n is odd then the outcome is -1
If n is even then the outcome is 1
This is some pretty out-of-the-box thinking, but it would be the only way to solve this without previous knowledge of complex functions including mod.
I am working with a legacy code base written in VB and have run into a conditional operator that I don't understand and cannot figure out what to search for to resolve it.
What I am dealing with is the following code and the variables that result as true. The specific parts that I do not understand are (1) the relationship between the first X and the first parens (-2 and (2) the role of X < 2
If X is a value below -2 it evaluates as false.
If X is a value above 2 it evaluates as true.
If Y is below 5 it evaluates to true as expected.
X = 3
Y = 10
If X > (-2 And X < 2) Or Y < 5 Then
'True
Else
'False
End If
I'm gonna leave off the Or Y < 5 part of the expression for this post as uninteresting, and limit myself to the X > (-2 And X < 2) side of the expression.
I haven't done much VB over the last several years, so I started out with some digging into Operator Precedence rules in VB, to be sure I have things right. I found definitive info on VBA and VB.Net, and some MSDN stuff that might have been VB6 but could also have been the 2013 version of VB.Net. All of them, though, gave the < and > comparison operators higher precedence over the And operator, regardless of whether you see And as logical or bitwise.
With that info, and also knowing that we must look inside parentheses first, I'm now confident the very first part of the expression to be evaluated is X < 2 (rather than -2 And X). Further, we know this will produce a Boolean result, and this Boolean result must be then converted to an Integer to do a bitwise (not logical) And with -2. That result (I'll call it n), which is still an Integer, can at last be compared to see if X > n, which will yield the final result of the expression as a Boolean.
I did some more digging and found this Stack Overflow answer about converting VB Booleans to Integers. While not definitive documentation, I was once privileged to meet the author (Hi #JaredPar) and know he worked on the VB compiler team at Microsoft, so he should know what he's talking about. It indicates that VB Boolean True has the surprising value of -1 as an integer! False becomes the more-normal 0.
At this point we need to talk about the binary representation of negative numbers. Using this reference as a guide (I do vaguely remember learning about this in college, but it's not the kind of thing I need every day), I'm going to provide a conversion table for integers from -3 to +3 in an imaginary integer size of only 4 bits (short version: invert the bit pattern and add one to get the negative representation):
-3 1101
-2 1110
-1 1111 --this helps explain **why** -1 was used for True
0 0000
1 0001
2 0010
3 0010
Stepping back, let's now consider the original -2 And X < 2 parenthetical and look at the results from the True (-1) and False (0) possible outcomes for X < 2 after a bitwise And with -2:
-2 (1110) And True (1111) = 1110 = -2
-2 (1110) And False (0000) = 0000 = 0
Really the whole point here from using the -1 bit pattern is anything And True produces that same thing you started with, whereas anything And False produces all zeros.
So if X < 2 you get True, which results in -2; otherwise you end up with 0. It's interesting to note here that if our language used positive one for True, you'd end up with the same 0000 value doing a bitwise And with -2 that you get from False (1110 And 0001).
Now we know enough to look at some values for X and determine the result of the entire original expression. Any positive integer is greater than both -2 and 0, so the expression should result in True. Zero and -1 are similar: they are less than two, and so will be compared again only as greater than -2 and thus always result in True. Negative two, though, and anything below, should be False.
Unfortunately, this means you could simplify the entire expression down to X > -2. Either I'm wrong about operator precedence, my reference for negative integer bit patterns is wrong, you're using a version of VB that converts True to something other than -1, or this code is just way over-complicated from the get-go.
I believe the sequence is as follows:
r = -2 and X 'outputs X with the least significant bit set to 0 (meaning the first lesser even number)
r = (r < 2) 'outputs -1 or 0
r = (X > r) 'outputs -1 or 0
r = r Or (Y < 5)
Use AndAlso and OrElse.
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.
In natural languages, we would say "some color is a primary color if the color is red, blue, or yellow."
In every programming language I've seen, that translates into something like:
isPrimaryColor = someColor == "Red" or someColor == "Blue" or someColor == "Yellow"
Why isn't there a syntax that more closely matches the English sentence. After all, you wouldn't say "some color is a primary color if that color is red, or that color is blue, or that color is yellow."
I realize simply isPrimaryColor = someColor == ("Red" or "Blue" or "Yellow") because instead of Red Blue and Yellow they could be boolean statement in which case boolean logic applies, but what about something like:
isPrimaryColor = someColor ( == "Red" or == "Blue" or == "Yellow")
As an added bonus that syntax would allow for more flexibility, say you wanted to see if a number is between 1 and 100 or 1000 and 2000, you could say:
someNumber ((>= 1 and <=100) or (>=1000 and <=2000))
Edit:
Very interesting answers, and point taken that I should learn more languages. After reading through the answers I agree that for strictly equality comparison something similar to set membership is a clear and concise way of expressing the same thing (for languages that have language support for concise inline lists or sets and testing membership)
One issues that came up is that if the value to compare is the result of an expensive calculation a temporary variable would need to be (well, should be) created. The other issue is that there may be different evaluations that need to be checked, such as "the result of some expensive calculation should be prime and between 200 and 300"
These scenarios are also covered by more functional languages (though depending on the language may not be more concise), or really any language that can take a function as a parameter. For instance the previous example could be
MeetsRequirements(GetCalculatedValue(), f(x):x > 200, f(x):x < 300, IsPrime)
I think that most people consider something like
isPrimaryColor = ["Red", "Blue", "Yellow"].contains(someColor)
to be sufficiently clear that they don't need extra syntax for this.
In python you can do something like this:
color = "green"
if color in ["red", "green", "blue"]:
print 'Yay'
It is called in operator, which tests for set membership.
In perl 6 you could do this with junctions:
if $color eq 'Red'|'Blue'|'Green' {
doit()
}
Alternately you could do it with the smart match operator (~~). The following is roughly equivalent to python's if value in list: syntax, except that ~~ does a lot more in other contexts.
if ($color ~~ qw/Red Blue Green/) {
doit()
}
The parens also make it valid perl 5 (>=5.10); in perl 6 they're optional.
In Haskell, it is easy to define a function to do this:
matches x ps = foldl (||) False $ map (\ p -> p x) ps
This function takes a value list of predicates (of type a -> Bool) and returns True if any of the the predicates match the value.
This allows you to something like this:
isMammal m = m `matches` [(=="Dog"), (=="Cat"), (=="Human")]
The nice thing is that it doesn't have to just be equality, you can use anything with the correct type:
isAnimal a = a `matches` [isMammal, (=="Fish"), (=="Bird")]
Ruby
Contained in list:
irb(main):023:0> %w{red green blue}.include? "red"
=> true
irb(main):024:0> %w{red green blue}.include? "black"
=> false
Numeric Range:
irb(main):008:0> def is_valid_num(x)
irb(main):009:1> case x
irb(main):010:2> when 1..100, 1000..2000 then true
irb(main):011:2> else false
irb(main):012:2> end
irb(main):013:1> end
=> nil
irb(main):014:0> is_valid_num(1)
=> true
irb(main):015:0> is_valid_num(100)
=> true
irb(main):016:0> is_valid_num(101)
=> false
irb(main):017:0> is_valid_num(1050)
=> true
So far, nobody has mentioned SQL. It has what you are suggesting:
SELECT
employee_id
FROM
employee
WHERE
hire_date BETWEEN '2009-01-01' AND '2010-01-01' -- range of values
AND employment_type IN ('C', 'S', 'H', 'T') -- list of values
COBOL uses 88 levels to implement named values, named groups of values
and named ranges of values.
For example:
01 COLOUR PIC X(10).
88 IS-PRIMARY-COLOUR VALUE 'Red', 'Blue', 'Yellow'.
...
MOVE 'Blue' TO COLOUR
IF IS-PRIMARY-COLOUR
DISPLAY 'This is a primary colour'
END-IF
Range tests are covered as follows:
01 SOME-NUMBER PIC S9(4) BINARY.
88 IS-LESS-THAN-ZERO VALUE -9999 THRU -1.
88 IS-ZERO VALUE ZERO.
88 IS-GREATER-THAN-ZERO VALUE 1 THRU 9999.
...
MOVE +358 TO SOME-NUMBER
EVALUATE TRUE
WHEN IS-LESS-THAN-ZERO
DISPLAY 'Negative Number'
WHEN IS-ZERO
DISPLAY 'Zero'
WHEN IS-GREATER-THAN-ZERO
DISPLAY 'Positive Number'
WHEN OTHER
DISPLAY 'How the heck did this happen!'
END-EVALUATE
I guess this all happened because COBOL was supposed to emulate English
to some extent.
You'll love Perl 6 because it has:
chaining comparison operators:
(1 <= $someNumber <= 100) || (1000 <= $someNumber <= 2000))
junctive operators:
$isPrimaryColor = $someColor ~~ "Red" | "Blue" | "Yellow"
And you can combine both with ranges:
$someNumber ~~ (1..100) | (1000..2000)
Python actually gives you the ability to do the last thing quite well:
>>> x=5
>>> (1<x<1000 or 2000<x<3000)
True
In Python you can say ...
isPrimaryColor = someColor in ('Red', 'Blue', 'Yellow')
... which I find more readable than your (== "Red" or == "Blue") syntax. There's a few reasons to add syntax support for a language feature:
Efficiency: Not a reason here, since there's no speed improvement.
Functionality: Also not a concern; there's nothing you can do in the new syntax that you can't do in the old.
Legibility: Most languages handle the case where you're checking the equality of multiple values just fine. In other cases (e.g., someNumber (> 1 and < 10)) it might be more useful, but even then it doesn't buy you much (and Python allows you to say 1 < someNumber < 10, which is even clearer).
So it's not clear the proposed change is particularly helpful.
My guess would be that languages are designed by force of habit. Early languages only would have had binary comparison operators because they are simpler to implement. Everyone got used to saying (x > 0 and x < y) until language designers didn't ever bother to support the common form in mathematics, (0 < x < y).
In most languages a comparison operator returns a boolean type. In the case of 0 < x < y, if this is interpreted as (0 < x) < y it would be meaningless, since < does not make sense for comparing booleans. Therefore, a new compiler could interpret 0 < x < y as tmp:=x, 0 < tmp && tmp < y without breaking backward compatibility. In the case of x == y == z, however, if the variables are already booleans, it is ambiguous whether this means x == y && y == z or (x == y) == z.
In C# I use the following extension method so that you can write someColor.IsOneOf("Red", "Blue", "Yellow"). It is less efficient than direct comparison (what with the array, loop, Equals() calls and boxing if T is a value type), but it sure is convenient.
public static bool IsOneOf<T>(this T value, params T[] set)
{
object value2 = value;
for (int i = 0; i < set.Length; i++)
if (set[i].Equals(value2))
return true;
return false;
}
Icon has the facility you describe.
if y < (x | 5) then write("y=", y)
I rather like that aspect of Icon.
In C#:
if ("A".IsIn("A", "B", "C"))
{
}
if (myColor.IsIn(colors))
{
}
Using these extensions:
public static class ObjectExtenstions
{
public static bool IsIn(this object obj, params object [] list)
{
foreach (var item in list)
{
if (obj == item)
{
return true;
}
}
return false;
}
public static bool IsIn<T>(this T obj, ICollection<T> list)
{
return list.Contains(obj);
}
public static bool IsIn<T>(this T obj, IEnumerable<T> list)
{
foreach (var item in list)
{
if (obj == item)
{
return true;
}
}
return false;
}
}
You'll have to go a bit down the abstraction layer to find out the reason why. x86's comparison/jump instructions are binary (since they can be easily computed in a few clock cycles), and that's the way things have been.
If you want, many languages offer an abstraction for that. In PHP, for example you could use:
$isPrimaryColor = in_array($someColor, array('Red', 'White', 'Blue'));
I don't see an Objective-C answer yet. Here is one:
BOOL isPRimaryColour = [[NSSet setWithObjects: #"red", #"green", #"blue", nil] containsObject: someColour];
The question is reasonable, and I wouldn't regard the change as syntactic sugar. If the value being compared is the result of computation, it would be nicer to say:
if (someComplicatedExpression ?== 1 : 2 : 3 : 5)
than to say
int temp;
temp = someComplicatedExpression;
if (temp == 1 || temp == 2 || temp == 3 || temp == 5)
particularly if there was no other need for the temp variable in question. A modern compiler could probably recognize the short useful lifetime of 'temp' and optimize it to a register, and could probably recognize the "see if variable is one of certain constants" pattern, but there'd be no harm in allowing a programmer to save the compiler the trouble. The indicated syntax wouldn't compile on any existing compiler, but I don't think it would be any more ambiguous than (a+b >> c+d) whose behavior is defined in the language spec.
As to why nobody's done that, I don't know.
I'm reminded of when I first started to learn programming, in Basic, and at one point I wrote
if X=3 OR 4
I intended this like you are describing, if X is either 3 or 4. The compiler interpreted it as:
if (X=3) OR (4)
That is, if X=3 is true, or if 4 is true. As it defined anything non-zero as true, 4 is true, anything OR TRUE is true, and so the expression was always true. I spent a long time figuring that one out.
I don't claim this adds anything to the discussion. I just thought it might be a mildly amusing anecdote.
As a mathematician, I would say that the colour is primary if and only if it is a member of the set {red, green, blue} of primary colours.
And this is exactly how you could say in Delphi:
isPrimary := Colour in [clRed, clGreen, clBlue]
In fact, I employ this technique very often. Last time was three days ago. Implementing my own scripting language's interpreter, I wrote
const
LOOPS = [pntRepeat, pntDoWhile, pntFor];
and then, at a few lines,
if Nodes[x].Type in LOOPS then
The Philosophical Part of the Question
#supercat, etc. ("As to why nobody's done that, I don't know."):
Probably because the designers of programming languages are mathematicians (or, at least, mathematically inclined). If a mathematician needs to state the equality of two objects, she would say
X = Y,
naturally. But if X can be one of a number of things A, B, C, ..., then she would define a set S = {A, B, C, ...} of these things and write
X ∈ S.
Indeed, it is extremely common that you (mathematicians) write X ∈ S, where S is the set
S = {x ∈ D; P(x)}
of objects in some universe D that has the property P, instead of writing P(X). For instance, instead of saying "x is a positive real number", or "PositiveReal(x)", one would say x ∈ ℝ⁺.
It's because programming languages are influenced by mathematics, logic and set theory in particular. Boolean algebra defines ∧, ∨ operators in a way that they do not work like spoken natural language. Your example would be written as:
Let p(x) be unary relation which holds if and only if x is a primary color
p(x) ⇔ r(x) ∨ g(x) ∨ b(x)
or
p(x) ⇔ (x=red) ∨ (x=green) ∨ (x=blue)
As you see, it's pretty similar to notation that would be used in programming language. As mathematics provide strong theoretic foundations, programming languages are based on mathematics rather than natural language which always leaves a lot of space for interpretation.
EDIT: Above statement could be simplified by using set notation:
p(x) ⇔ x ∈ {red, green, blue}
and indeed, some programming languages, most notably Pascal, included set, so you could type:
type
color = (red, green, blue, yellow, cyan, magenta, black, white);
function is_primary (x : color) : boolean;
begin
is_primary := x in [red, green, blue]
end
But sets as a language feature didn't catch on.
PS. Sorry for my imperfect English.
The latter examples you give are effectively syntactic sugar, they'd have to evaluate to the same code as the longer form as at some point the executed code has to compare your value with each of the conditions in turn.
The array comparison syntax, given in several forms here, closer and I suspect there are other languages which get even closer.
The main problem with making syntax closer to natural language is that the latter is not just ambiguous, it's hideously ambiguous. Even keeping ambiguity to a minimum we still manage to introduce bugs into our apps, can you imagine what it would be like if you programmed in natural english?!
Just to add to language examples
Scheme
(define (isPrimaryColor color)
(cond ((member color '(red blue yellow)) #t)
(else #f)))
(define (someNumberTest x)
(cond ((or (and (>= x 1) (<= x 100)) (and (>= x 10000 (<= x 2000))) #t)
(else #f)))
Two possibilities
Java
boolean isPrimary = Arrays.asList("red", "blue", "yellow").contains(someColor);
Python
a = 1500
if 1 < a < 10 or 1000 < a < 2000:
print "In range"
This can be replicated in Lua with some metatable magic :D
local function operator(func)
return setmetatable({},
{__sub = function(a, _)
return setmetatable({a},
{__sub = function(self, b)
return f(self[1], b)
end}
)
end}
)
end
local smartOr = operator(function(a, b)
for i = 1, #b do
if a == b[i] then
return true
end
end
return false
end)
local isPrimaryColor = someColor -smartOr- {"Red", "Blue", "Either"}
Note: You can change the name of -smartOr- to something like -isEither- to make it even MORE readable.
Languages on computers compare as binary because they are all for a machine that uses binary to represent information. They were designed using similar logic and with broadly similar goals. The English language wasn't designed logically, designed to describe algorithms, and human brains (the hardware it runs on) aren't based on binary. They're tools designed for different tasks.