C# Bitwise Operator With Ints - c#

What does this expression actually mean??
Note - the x and y vars are just sample values.
int x = 3;
int y = 1;
if ((x & y) !=0)
I inherited a codebase and am not up to speed on bitwise operators. I have read up, but am still missing something. Help!

It's comparing the bits in each value. It returns any bits that are set in both numbers.
In your example:
3: 0011
1: 0001
3 & 1: 0001

This checks whether x and y both have at least one common bit set. In the case of your example this would be the true.

if ((x & y) != 0)
This would typically be used to determine whether the value x has a specific bit-flag (y) set. The AND operator returns an integer with only those bits set that are set in both operands.

Related

Does double z=x-y guarantee that z+y==x for IEEE 754 floating point?

I have a problem that can be reduced to this problem statement:
Given a series of doubles where each is in the range [0, 1e7],
modify the last element such that the sum of the numbers equals
exactly a target number. The series of doubles already sums to the
target number within an epsilon (1e-7), but they are not ==.
The following code is working, but is it guaranteed to work for all inputs that meet the requirements described in the first sentence?
public static double[] FixIt(double[] input, double targetDouble)
{
var result = new double[input.Length];
if (input.Length == 0) return result;
double sum = 0;
for (int i = 0; i < input.Length - 1; i++)
{
sum += input[i];
result[i] = input[i];
}
double remainder = targetDouble - sum;
result[result.Length - 1] = remainder;
return result;
}
var arr1 = Enumerable.Repeat(Math.PI / 13, 13).ToArray();
var arr2 = FixIt(arr1, Math.PI);
Debug.Print(Math.PI.ToString("R")); //3.1415926535897931
Debug.Print(arr1.Sum().ToString("R")); //3.1415926535897922
Debug.Print(arr2.Sum().ToString("R")); //3.1415926535897931
A previous version of this question asked about modifying the first element, but modifying the last element simplifies the problem to a known sum and a known target, leaving us with just the question of whether last = target-sum implies that sum+last == target.
(Without NaN of course, and the restrictions on ranges imply some restrictions on last as well that might help.)
Regarding the real problem: We've had this problem surface a number of times in a variety of ways, but what we are trying to do at the moment is reduce the floating point error that crops up due to numerical instabilities in a linear programming solver (Coin-OR CBC). For example, there are 6 variables which all must be in the range [0,X] and the sum of the variables must also be X. Due to numerical instability, the solver occasionally returns slightly negative values and values that do not sum to exactly X. We've overcome the negative number issues - now just trying to resolve the sum to X issue. (Yes, there may be constraints that are being disobeyed by us changing the results, but making sure these numbers sum to X is of higher priority, where the other constraints are not as important.)
z = x-y; does not guarantee z+y == x, and there is not always a solution for the problem of finding a z such z+y == x. A proof follows.
We assume IEEE-754 binary floating-point arithmetic with rounding to nearest, ties to even. The basic 64-bit format is used, but the result holds for other formats. Note that the 64-bit format uses 53-bit significands, meaning that only numbers with 53 or fewer significant binary digits can be represented.
Consider a target x equal to 1+2−52. Let y be 2−53. Then, after z = x-y;, z+y == x evaluates to false. The arithmetic details are shown below, but:
z = x-y; sets z to 1, and then z+y produces 1, which is less than x.
If we increase z to the next representable number, 1+2−52, then z+y produces 1+2−51, which is greater than x.
So there is no value of z that makes z+y == x true.
Details:
The mathematical result of x−y is 1+2−53. As this has 54 significant bits (from 20 to 2−53), it is not representable, and the computed result of x-y must be rounded. The two nearest numbers are 1 and 1+2−52. The ties-to-even rule produces the former number, 1, as the low bit of its significand is 0, while the low bit for 1+2−52 is 1.
Thus z = x-y; sets z to 1.
Then the mathematical result of z+y is 1+2−53. As above, this is rounded to 1, so the computed result of z+y is 1. So z+y == x compares 1 to 1+2−52 and produces false.
Furthermore, no value of z could make the comparison true. If we increment z by the smallest available step, from 1 to 1+2−52, the mathematical sum of z+y is then 1+2−52+2−53. This is midway between the two representable numbers 1+2−52 and 1+2−51. The former has a low bit of 1, and the latter has a low bit of 0, so the computed result of this z+y is 1+2−51, which is of course not equal to 1+2−52.
Floating-point addition is weakly monotonic, so there are no values of z that would produce 1+2−52 for z+y.
No, it doesn't. Here's a concrete counter-example; coded in Python, but you can easily repeat the same experiment in C#:
>>> x = 0.24999916553497312
>>> y = 1.0000153779983518
>>> z = -0.7500162124633787
>>> z == x - y
True
>>> z + y == x
False
Here's a small counter-example with x, y, z all positive:
>>> x = 0.4500000000000001
>>> y = 0.20000000000000004
>>> z = 0.2500000000000001
>>> z == x - y
True
>>> z + y == x
False
Floating point arithmetic is not exact, by definition (unless you're only dealing with integers (edit for correctness: up to 253 i.e. 9007199254740992)); you will always have rounding discrepancies. If you want the rounding to match what humans expect: use decimal instead of double. If you do the same thing with decimal, it will work correctly for any set of numbers that aren't pathological in terms of the decimal digits.

Get the sign of a number in C# without conditional statement

Just out of curiosity, is there a way to get the sign of a number, any kind (but obviously a signed type), not just integer using some bitwise/masking, or other kind of, operation?
That is without using any conditional statement or calling the Math.Sign() function.
Thanks in advance!
EDIT: I recognize it was a misleading question. What I had in mind more likely something like: "get the same output of the Math.Sign() or, simplifying get 0 if x <= 0, 1 otherwise".
EDIT #2: to all those asking for code, I didn't have any in mind when I posted the question, but here's an example I came up with, just to give a context of a possible application:
x = (x < 0) ? 0 : x;
Having the sign into a variable could lead to:
x = sign * x; //where sign = 0 for x <= 0, otherwise sign = 1;
The aim would be to achieve the same result as the above :)
EDIT #3: FOUND IT! :D
// THIS IS NOT MEANT TO BE PLAIN C#!
// Returns 0 if x <= 0, 1 otherwise.
int SignOf(x)
{
return (1+x-(x+1)%x)/x;
}
Thanks to everyone!
is there a way to get the sign of a number (any kind, not just integer)
Not for any number type, no. For an integer, you can test the most significant bit: if it's 1, the number is negative. You could theoretically do the same with a floating point number, but bitwise operators don't work on float or double.
Here's a "zero safe" solution that works for all value types (int, float, double, decimal...etc):
(value.GetHashCode() >> 31) + 1;
Output: 1 = 1, -1 = 0, 0.5 = 1, -0.5 = 0, 0 = 1
It's also roughly 10% cheaper than (1+x-(x+1)%x)/x; in C#. Additionally if "value" is an integer, you can drop the GetHashCode() function call in which case (1+x-(x+1)%x)/x; is 127% more expensive ((value >> 31) + 1; is 56% cheaper).
Since 0 is positive it is illogical for a result of 1 for positive numbers & a result of 0 for 0. If you could parametrise -0 you would get an output of 0.
I understand that GetHashCode() is a function call, but the inner workings of the function in the C# language implementation is entirely "arithmetic". Basically the GetHashCode() function reads the memory section, that stores your float type, as an integer type:
*((int*)&singleValue);
How the GetHashCode function works (best source I could find quickly) - https://social.msdn.microsoft.com/Forums/vstudio/en-US/3c3fde60-1b4a-449f-afdc-fe5bba8fece3/hash-code-of-floats?forum=netfxbcl
If you want the output value to be 1 with the same sign as the input, use:
((float.GetHashCode() >> 31) * 2) + 1;
The above floating-point method is roughly 39% cheaper than System.Math.Sign(float) (System.Math.Sign(float) is roughly 65% more expensive). Where System.Math.Sign(float) throws an exception for float.NaN, ((float.NaN.GetHashCode() >> 31) * 2) + 1; does not and will return -1 instead of crashing.
or for integers:
((int >> 31) * 2) + 1;
The above integer method is roughly 56% cheaper than System.Math.Sign(int) (System.Math.Sign(int) is roughly 125% more expensive).
It depends on the type of number value type you are targeting.
For signed Integers C# and most computer systems use the so called Ones' complement representation.
That means the sign is stored in the first bit of the value.
So you can extract the sign like this:
Int16 number = -2;
Int16 sign = (number & Int16.MinValue) >> 16;
Boolean isNegative = Convert.ToBoolean(sign);
Note that up until now we have not used any conditional operator (explicitly anyways)
But: You still don't know whether the number has a sign or not.
The logical equivalent of your question: "How do I know, if my number is negative?" explicitly requires the usage of a conditional operator as the question is, after all conditional.
So you won't be able to dodge:
if(isNegative)
doThis();
else
doThat();
to just get the sign, you can avoid conditional operators as you will see below in Sign extension of int32 struct. however to get the name I dont think you can avoid conditional operator
class Program
{
static void Main(string[] args)
{
Console.WriteLine(0.Sign());
Console.WriteLine(0.SignName());
Console.WriteLine(12.Sign());
Console.WriteLine(12.SignName());
Console.WriteLine((-15).Sign());
Console.WriteLine((-15).SignName());
Console.ReadLine();
}
}
public static class extensions
{
public static string Sign(this int signedNumber)
{
return (signedNumber.ToString("+00;-00").Substring(0, 1));
}
public static string SignName(this int signedNumber)
{
return (signedNumber.ToString("+00;-00").Substring(0, 1)=="+"?"positive":"negative");
}
}
if x==0 you will have a divby0 exception with this code you posted:
int SignOf(x) {
return (1+x-(x+1)%x)/x; }

C# compound assignment operator ^=

What does this operator ^= mean in c#?
It means bitwise XOR the value of the LHS expression with the value of the RHS expression, and assign it back to the LHS expression.
So for example:
int x = 10;
int y = 3;
x ^= y; // x = 10 ^ 3, i.e. 9
The LHS expression is only evaluated once, so if you have:
array[GetIndex()] ^= 10;
that would only call GetIndex once. But please don't do that, 'cos it's nasty :)
See also the relevant MSDN page.
You may also find Eric Lippert's recent April Fool's Day blog post on compound assignment operators amusing - and part one of the series, which was rather more serious, may prove enlightening.
this:
x ^= y;
is equivalent to this:
x = x ^ y;
In words, set x to the value of x exclusive or'ed with y.
The exclusive-OR assignment operator.
An expression of the form
x ^= y
is evaluated as
x = x ^ y
except that x is only evaluated once. The ^ operator performs a bitwise exclusive-OR operation on integral operands and logical exclusive-OR on bool operands.
http://msdn.microsoft.com/en-us/library/0zbsw2z6.aspx
This is the "exclusive or assignment" operator. Details are at http://msdn.microsoft.com/en-us/library/0zbsw2z6(v=VS.100).aspx
XOR. a ^= b is the same as a = a ^ b, where a and b are integer types of some sort.

Return zero for negative integers

A friend just throw some code similar to following C# code:
int i = ...;
return i < 0 ? 0 : i;
That made me think. There's any "different" way to return zero for negative integers, or current positive value? More specifically I'm looking for bitwise operations, if possible.
BTW, I'm aware of Math.Max(0, i);
What's wrong with Math.Max?
You can do the equivalent without a branch using bitwise operations:
r = x ^ ((x ^ y) & -(x < y)); // == max(x, y)
If you substitute zero, it collapses to:
r = (y & -(0 < y)); // == max(0, y)
(Source: this list of bitwise tricks.)
If branches were extremely expensive on your platform, that might be worthwhile in some inner loop, I suppose, but it's pretty obscure and not the kind of thing I'd like to come across outside of an extremely time-sensitive function.
How about:
int i = ...;
return i & ~(i >> 31);
The below will do the trick and the code reads so well it practically don't need a comment ;)
((((0x80000000 & i) >> 31)^1) * 0xFFFFFFFF) & i
then again
int temp = (0x80000000 & i); //get the most significant bit (1 for negative 0 for positive)
temp = (temp>>31)^1; //more it to the least significant and not it (we now have 0 for negative numbers and one for positive)
temp *= 0xFFFFFFFF; //get a lof of F's if it's positive or a lot of zeros if the number was negative
temp = temp & i; //and the F's/zeros with the original number
and voila zero for all negative number and all positive are left unchanged
Short answer: No.
Bit operators do something very different, or rather are used for different problems.
If you know the size of your integers, you could test the highest (most significant) bit; if it's 1, the number is negative and you can act on that. But that would be a heck of a lot more work than the simple "<" test.
Not bitwise but different:
return (i + Math.abs(i))/2
EDIT:
return (int)(i/2f + Math.abs(i)/2f)

Why doesn't this overflow?

Given this code:
int x = 20000;
int y = 20000;
int z = 40000;
// Why is it printing WTF? Isn't 40,000 > 32,767?
if ((x + y) == z) Console.WriteLine("WTF?");
And knowing an int can hold −32,768 to +32,767. Why doesn't this cause an overflow?
In C#, the int type is mapped to the Int32 type, which is always 32-bits, signed.
Even if you use short, it still won't overflow because short + short returns an int by default. If you cast this int to short - (short)(x + y) - you'll get an overflowed value. You won't get an exception though. You can use checked behavior to get an exception:
using System;
namespace TestOverflow
{
class Program
{
static void Main(string[] args)
{
short x = 20000;
short y = 20000;
short z;
Console.WriteLine("Overflowing with default behavior...");
z = (short)(x + y);
Console.WriteLine("Okay! Value is {0}. Press any key to overflow " +
"with 'checked' keyword.", z);
Console.ReadKey(true);
z = checked((short)(x + y));
}
}
}
You can find information about checked (and unchecked) on MSDN. It basically boils down to performance, because checking for overflow is a little bit slower than ignoring it (and that's why the default behavior is usually unchecked, but I bet that in some compilers/configurations you'll get an exception on the first z assignment.)
http://msdn.microsoft.com/en-us/library/5kzh1b5w.aspx
Type: int
Range: -2,147,483,648 to 2,147,483,647
While everyone is correct in saying that an "int" type on a 32 bit machine is most likely 2^32, there is a glaring flaw in your methodology.
Let's assume that int was 16 bit. You're assigning a value that will overflow z, so z itself is overflowed. When you calculate x+y you're also overflowing the int type, it's very likely that both cases will overflow to the same value, meaning you'd hit your equality regardless(this is probably compiler dependent, I'm not quite sure whether x+y will be promoted).
The correct way to do your experiment would be for z to have a larger data type than x and y. For example(Sorry for plain C, I'm not much of C# person. Hopefully it illustrated the methodology, however.)
int x = INT_MAX;
int y = INT_MAX;
int sum = x + y;
long long z = INT_MAX+INT_MAX;
if(sum == z)
printf("Why didn't sum overflow?!\n");
Comparing sum and z is important as comparing x+y and z may still come out fine depending on how the compiler handles promotion.
In C#, an Int is 4 bytes. So it maxes out at 2^31 or 2,147,483,648. If you want a 2 byte integer, use a short instead of an int.
Because an int in .NET is a signed 32 bit number with a range of -2,147,483,648 to 2,147,483,647.
Reference : http://msdn.microsoft.com/en-us/library/5kzh1b5w(VS.80).aspx
Because ints are 32-bit, holding values up to ±2GB.
An int's size is 4 byte so it can hold at least 2^31 which is around 2 billion.
The int keyword maps to the .NET Framework Int32 type, which can hold integers in the range from -2,147,483,648 to 2,147,483,647.
in C# int (System.Int32) is of 32 bits which can happily store this value.
you are given to print the result as "WTF?" .Then how should it display other value.
Int means int32 its range is –2147483648 to 2147483647
you are given the range of int16 :–32768 to 32767
This is the reason it is not throwing any error
First of all your code is in the range for int... However if it were not in the range then it wont complain either... coz you are never assigning a value back to any variable after doing X+Y in your if check...
Suppose if you were doing X * Y then it'll be calculated and the result would be a long value then the value from variable Z is taken and promoted to a long then both would be compared... Remember the casting from a lower range primitive to upper range primitive value is implicit.
int x = 200000; //In your code it was 20000
int y = 200000; //In your code it was 20000
int z = 40000;
// Why is it printing WTF? Isn't 40,000 > 32,767?
// Note: X + Y = 200000 and not < 32,767
// would pass compiler coz you are not assigning and values are compared as longs
// And since it's not equals to 40,000 the WTF did not got printed
if ((x + y) == z) Console.WriteLine("WTF?");
// And x * y >= z is true WTF MULTIPLY got printed
if ((x * y) >= z) Console.WriteLine("WTF MULTIPLY?");
// Compiler would fail since x can't hold 40,00,00,00,000
x = x * y;
All the above is true, however, it's important to know, that if you assign a number greater than 2^32, it will not compile!

Categories

Resources