So, I'm learning the code for the SplitMix64 generator and came upon this part here:
uint64_t z = (x += 0x9e3779b97f4a7c15);
Not being a C programmer, I don't really understand this construct.
Does the above mean z gets assigned value of x after x is incremented, like so:
x += 0x9e3779b97f4a7c15;
z = x;
Or does that mean z gets the value of x before x is incremented, like so:
z = x;
x += 0x9e3779b97f4a7c15;
And also, does the same behavior happen in C# ?
z gets assigned value of x after x is incremented. Think of it like this:
z = (x = x + 0x9e3779b97f4a7c15);
The return value of an assignment is always the value of the left-hand side of the assignment after the assignment is completed.
Related
I tried to search on Google and Bing this but both return zero results....
What does it mean when you put a hyphen in front of convert?
-Convert.ToSingle
It's just the - operator, applied to the result of calling Convert.ToSingle(...).
So for example when used as a unary operator:
double x = 10.52123;
float y = -Convert.ToSingle(x);
is equivalent to:
double x = 10.52123;
float tmp = Convert.ToSingle(x);
float y = -tmp;
Or when used as a binary operator:
double x = 10.52123;
float y = 10-Convert.ToSingle(x);
is equivalent to:
double x = 10.52123;
float tmp = Convert.ToSingle(x);
float y = 10 - tmp;
I'd say it's shorthand for
-1 * Convert.ToSingle(...)
Since the method returns a Single (which is a number, so it's subject to arithmetic operators)
The - operator is an unary or a binary operator. The result of a unary - operation on a numeric type is the numeric negation of the operand. For an example
int x = 5;
float b = -Convert.ToSingle(x);
Console.WriteLine(b);
Here the output should be -5. In the absence of unary operator. The output value should have been just 5
Just think about the C# syntax: what means a minus at the right of an assignment? In every language (or almost, don't talk to me about Brainfuck & co), it means change the sign of the number which following.
So the operation after this minus has to return a Number. Good, that's what Convert.ToSingle does, which returns a float.
float x = - Convert.ToSingle(42);
^ ^^^^^^^^^^^^^^^^
^ function call
minus operation
// equivalent to:
float x = 0 - Convert.ToSingle(42);
^^^
0 minus the result
Ive seen the following syntax in a couple of code samples, it looks pretty obvious, but not in the context that i saw it in,
so can someone confirm
var x = 1
var y = 2
var z = 3
x = y = z
so in essence does this mean that
x and y both equal z?
tried to google this, and couldn't find the syntax, also looked in murach .net books with no luck
The assignment operator returns the value being assigned as it's result
The assignment operator (=) stores the value of its right-hand operand in the storage location, property, or indexer denoted by its left-hand operand and returns the value as its result.
So
x = y = z;
Is parsed as
x = (y = z);
And this is equivalent to
y = z;
x = y;
In the end, x, and y are assigned the same value as z (in this case, 3).
This will indeed set x and y to the value of z, however to see why you can parenthesize the expression:
x = (y = z);
In this case the y = z expression will return the new value for y (in this case 3), and set x to that value.
This works for very long expressions too:
x = y = z = a = b
x = (y = (z = (a = b)))
Where x, y, z and a will be set to the value of b.
EDIT:
Also remember the order of precedence of operators when using this method of reading into a long expression, while its not a good practice to create huge chained statements you do sometimes see it in code online, another (and better) way you can use to read confusing statements like this is to think of the syntax tree that is generated.
Ehm, yes that is correct :).
x, y and x will all be 3 as you can assign values like that.
you can make the chain as long as you like too.
a = b = c = d;
all preceding values would be the value of d
void swap(ref int x, ref int y)
{ x = x ^ y; y = y ^ x; x = x ^ y; }
im learning about bitwise XOR. how is this swapping occurring? it's blowing my mind. this method is supposed to swap the contents of X and Y, but i dont understand AT ALL what is going on?
Beware. This method has a very very nasty property. It was used in one of the Underhanded C Contest entries. It will work happily... until one day someone tries something like swapping two array elements a[i] and a[j] without assuring that i!=j.
When both references refer to the same variable, this method zeroes it.
Wikipedia has an excellent explanation of the Swap-By-XOR algorithm.
The formal proof that this algorithm works is a bit involved, and requires the use of the mathematical properties of binary numbers.
But in simplified form, we can consider each bit of the binary value separate, since the XOR operation acts on each independently. As such, it's sufficient to show that this works with 1-bit values, since by induction we can demonstrate it works for any length binary value. It's quite simple to build an appropriate truth table for these operations, so I leave that out.
Swap by XOR is not the only "creative" swapping algorithm possible. A similar result can be achieved by using arithmetic operations:
void Swap( ref int x, ref int y )
{
x = x + y;
y = x - y;
x = x - y;
}
From a practical perspective, this is a technique that should be avoided in most cases. As you yourself recognize, the logic of this method is not immediately obvious and it can lead to maintainability and extensibility problems ... not the least of which is the fact that Swap( ref x, ref x ) will NOT do what the method's name implies (it will zero out the value, in fact).
Just look at it one bit at a time and one step at a time.
x|y -> x = x ^ y x|y -> y = y ^ x x|y -> x = x ^ x x|y
0|0 0|0 0|0 0|0
0|1 1|1 1|0 1|0
1|0 1|0 1|1 0|1
1|1 0|1 0|1 1|1
Here you can clearly see that the result in each case is a swapping of the bits. From here it is clear why it works in the general case. More formal explanations are possible.
Anytime you find yourself saying "I don't understand at all what is going on" is a strong indication that you should find a clearer way to write semantically-equivalent code.
swap() can be implemented with a single CPU instruction on most modern architectures (including i686 and x86_64). Hence, you are better off writing it in a way the compiler can recognize and convert accordingly rather than trying to micro optimize in a way that will actually make your code slower and less readable.
First of all look at how XOR works:
a | b | a^b
- - - - - -
0 | 0 | 0
1 | 0 | 1
0 | 1 | 1
1 | 1 | 0
So the result of an xor operation is 1 or true if the inputs are different, and 0 if the inputs are equal. Another way to look at it is to think of it as addition without carry, i'll denote it as (+) :
x = x ^ y <=> x = x (+) y;
y = y ^ x <=> y = y (+) x;
x = x ^ y <=> x = x (+) y;
First step : set all the bits that are 0 in x but 1 in y to 1. Now some bits are wrong in x because if a bit is 1 in x and also y it'll be set to 0. The other bits are correct.
Second step : Now set the same bit positions we set to 1 in x to 0 in y (we are done with y now). This works because x already has all bits that are different set to 1, so XORing y with x now basically means: toggle the bits in y that are set to 1 in x. We are done with y now :)
Third step : now we still need to set those bits in x to 1 that already were set to 1 originally and were reset to 0 after the first step back to 1. How ? We just XOR x with y one last time because what does xor do ? it sets a bit to 1 if the 2 inputs differ, which is exactly what we need.
If you are still confused about it you should just draw it on paper and play it through to see how it works and/or refer to the tables Jason did above.
What's up with this, anyway? I do a simple multiplication:
Int64 x = 11111111111;
Int64 y = 11111111111;
Int64 z = x * y;
And at the end of the multiplication, z shows a value of:
-5670418394979206991
This has clearly overflowed, but no exception is raised. I'd like one to be raised, but...
Note that this is on Windows Phone 7, but I don't think this has any bearing on the issue. Or does it?
You can use a checked block as pointed out already by other answers:
checked
{
long x = 11111111111;
long y = 11111111111;
long z = checked(x * y);
// ...
}
Which results in an exception:
OverflowException: Arithmetic operation resulted in an overflow.
If you are just doing a single operation where you need checking you can use a checked expression instead:
long x = 11111111111;
long y = 11111111111;
long z = checked(x * y);
You can also set the /checked compiler option to have the default be checked.
To set this compiler option in the Visual Studio development environment:
Open the project's Property Pages dialog box. For details, see Setting Visual C# Project Properties.
Click the Configuration Properties folder.
Click the Build property page.
Modify the Check for Arithmetic Overflow/Underflow property.
If you change the default to checked you can use unchecked blocks or expressions to get the unchecked behaviour again.
Check it:
checked
{
Int64 x = 11111111111;
Int64 y = 11111111111;
Int64 z = x * y;
}
Try:
checked
{
Int64 x = 11111111111;
Int64 y = 11111111111;
Int64 z = x * y;
}
Compiler assumes you want to do it that way and proceed with the Overflow. If overflow needs to be considered as exception for the operation, wrap the operation around checked and it will throw an exception at runtime.
checked
{
Int64 x = 11111111111;
Int64 y = 11111111111;
Int64 z = x * y;
}
System.OverflowException: An exception
of type System.OverflowException was
thrown.
int x = 10;
x += x--;
In C#/.Net, why does it equal what it equals? (I'm purposely leaving the answer out so you can guess and see if you're right)
Look at this statement:
x += x--;
This is equivalent to:
x = x + x--;
Which is equivalent to:
int a1 = x; // a1 = 10, x = 10
int a2 = x--; // a2 = 10, x = 9
x = a1 + a2; // x = 20
So x is 20 afterwards - and that's guaranteed by the spec.
What's also pretty much guaranteed, although not by the spec, is that anyone using such code will be attacked by their colleagues. Yes, it's good that the result is predictable. No, it's not good to use that kind of code.
Jon is of course right.
A good way to think about this is to remember:
1) subexpressions are always evaluated left to right. Period. Evaluation of a subexpression may induce a side effect.
2) execution of operators is always done in the order indicated by parentheses, precedence and associativity. Execution of operators may induce a side effect.
The "x" to the left of the += is the leftmost subexpression, and therefore rule (1) applies. Its value is computed first -- 10.
The x-- to the right of the += is the next one in left-to-right order, so it is evaluated next. The value of x-- is 10, and the side effect is that x becomes 9. This is as it should be, because -- is of higher precedence than +=, so its side effect runs first.
Finally, the side effect of += runs last. The two operands were 10 and 10, so the result is to assign 20 to x.
I get questions about this all the time. Remember, the rules are very straightforward: subexpressions left-to-right, operators in precedence order, period.
In particular, note that the commonly-stated reasoning "the -- operator is postfix and therefore runs after everything else" is incorrect reasoning. I discuss why that is incorrect in the articles below.
Here are some articles I've written on this subject:
http://blogs.msdn.com/ericlippert/archive/tags/precedence/default.aspx
20; the "--" doesn't happen until after everything gets evaluated, and that value is overwritten by the left-hand side of the equals.
From the specs 7.13.2
If the return type of the selected operator is implicitly convertible to the type of x, the operation is evaluated as x = x op y, except that x is evaluated only once.
So your statement is equivalent to x = x + x--; which is evaluated in left-to-right order and gives the answer 20.
Note that there is also a difference between --x and x-- here. If you had written x += --x; this would be equivalent to x = x + --x; then you would get 19. This is because the value of x is decremented and the resulting value is used in the expression (unlike x-- where the original value of x is used in the expression).
This expression x = x + --x + x will give 28 because the third timefourth time (see comments) x is evaluated it is 9.
The answer is 20. And Tom, you really aren't as surprised as your questions seems to imply, right? And to those of you who are assuming the answer is 19 - I think you're confused with x += --x;