Related
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.
For the below FOR loop in VB.net (a simplified version of my code), the encased logic is only hit twice. I had assumed the end case being 10 and 50 would be interpreted as "continue if i < 10 AND i < 50" but that does not seem to be the case.
For i As Integer = 0 To 10 And 50
'...logic...
Next
What is the correct interpretation, and is there a way to create a FOR loop with multiple end cases?
Your loop is equivalent to
Dim t = 10 And 50
For i As Integer = 0 To t
' something '
Next
where 10 And 50 is a bitwise AND operation on two Integer numbers. And because 10 And 50 returns 2 you get loop from 0 to 2.
Might And be bitwise and? 10 = 8+2, and 50 = 32+16+2, so the bitwise and would just be 2.
The syntax of the For statement is (edited to fit):
For LoopControlVariable Equals Expression To Expression [Step Expression ]
So the And keyword plays no special role in the statement, it is simply part of the To expression. With integral operands, it performs a mathematical AND operation that performs a bitwise AND on the bits in the integral value.
Since 10 And 50 equals 00001010 And 00110010 in binary = 00000010 in binary or 2 in decimal, the loops iterates from 0 to 2 inclusive.
What are you trying to accomplish? Why do you it to be for i<10 and i<50? Wouldn't you just need for i<50?
So I thought that negative numbers, when mod'ed should be put into positive space... I cant get this to happen in objective-c
I expect this:
-1 % 3 = 2
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
But get this
-1 % 3 = -1
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
Why is this and is there a workaround?
result = n % 3;
if( result < 0 ) result += 3;
Don't perform extra mod operations as suggested in the other answers. They are very expensive and unnecessary.
In C and Objective-C, the division and modulus operators perform truncation towards zero. a / b is floor(a / b) if a / b > 0, otherwise it is ceiling(a / b) if a / b < 0. It is always the case that a == (a / b) * b + (a % b), unless of course b is 0. As a consequence, positive % positive == positive, positive % negative == positive, negative % positive == negative, and negative % negative == negative (you can work out the logic for all 4 cases, although it's a little tricky).
If n has a limited range, then you can get the result you want simply by adding a known constant multiple of 3 that is greater that the absolute value of the minimum.
For example, if n is limited to -1000..2000, then you can use the expression:
result = (n+1002) % 3;
Make sure the maximum plus your constant will not overflow when summed.
We have a problem of language:
math-er-says: i take this number plus that number mod other-number
code-er-hears: I add two numbers and then devide the result by other-number
code-er-says: what about negative numbers?
math-er-says: WHAT? fields mod other-number don't have a concept of negative numbers?
code-er-says: field what? ...
the math person in this conversations is talking about doing math in a circular number line. If you subtract off the bottom you wrap around to the top.
the code person is talking about an operator that calculates remainder.
In this case you want the mathematician's mod operator and have the remainder function at your disposal. you can convert the remainder operator into the mathematician's mod operator by checking to see if you fell of the bottom each time you do subtraction.
If this will be the behavior, and you know that it will be, then for m % n = r, just use r = n + r. If you're unsure of what will happen here, use then r = r % n.
Edit: To sum up, use r = ( n + ( m % n ) ) % n
I would have expected a positive number, as well, but I found this, from ISO/IEC 14882:2003 : Programming languages -- C++, 5.6.4 (found in the Wikipedia article on the modulus operation):
The binary % operator yields the remainder from the division of the first expression by the second. .... If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined
JavaScript does this, too. I've been caught by it a couple times. Think of it as a reflection around zero rather than a continuation.
Why: because that is the way the mod operator is specified in the C-standard (Remember that Objective-C is an extension of C). It confuses most people I know (like me) because it is surprising and you have to remember it.
As to a workaround: I would use uncleo's.
UncleO's answer is probably more robust, but if you want to do it on a single line, and you're certain the negative value will not be more negative than a single iteration of the mod (for example if you're only ever subtracting at most the mod value at any time) you can simplify it to a single expression:
int result = (n + 3) % 3;
Since you're doing the mod anyway, adding 3 to the initial value has no effect unless n is negative (but not less than -3) in which case it causes result to be the expected positive modulus.
There are two choices for the remainder, and the sign depends on the language. ANSI C chooses the sign of the dividend. I would suspect this is why you see Objective-C doing so also. See the wikipedia entry as well.
Not only java script, almost all the languages shows the wrong answer'
what coneybeare said is correct, when we have mode'd we have to get remainder
Remainder is nothing but which remains after division and it should be a positive integer....
If you check the number line you can understand that
I also face the same issue in VB and and it made me to forcefully add extra check like
if the result is a negative we have to add the divisor to the result
Instead of a%b
Use: a-b*floor((float)a/(float)b)
You're expecting remainder and are using modulo. In math they are the same thing, in C they are different. GNU-C has Rem() and Mod(), objective-c only has mod() so you will have to use the code above to simulate rem function (which is the same as mod in the math world, but not in the programming world [for most languages at least])
Also note you could define an easy to use macro for this.
#define rem(a,b) ((int)(a-b*floor((float)a/(float)b)))
Then you could just use rem(-1,3) in your code and it should work fine.