I have a piece of C# code that another developer has copied from a blog post which is used to encode/obfuscate an integer. this code contains some syntax that i am unfamiliar with. It looks like it might be rounding down the result of the calculation to prevent it from exceeding the maximum size of an integer, if that is the case i am worried that two input values could potentially result in the same output. The obfuscated values need to be unique so i'm worried about using this code without understanding how it works
this is a simplified version of the code:
public static int DecodeNumber(int input)
{
return (input * PrimeInverse) & int.MaxValue;
}
so my question is
what is the meaning of the ampersand in this context and will this code produce an output that is unique to the input?
No, there is no "rounding" going on here. This is a sneaky way of truncating the most significant bit when multiplication results in overflow.
According to the documentation, int.MaxValue is 2,147,483,647, which is 0x7FFFFFFF in hex. Performing a bitwise AND with this value simply clears out the most significant bit.
Since the intention of the code is to use int.MaxValue for its binary pattern, rather than for its numeric value of the highest int that could be represented by Int32, I would recommend either using 0x7FFFFFFF constant explicitly, or computing it with ~ expressionL
return (input * PrimeInverse) & ~(1 << 31);
The ampersand is a bitwise AND operator. The numbers on the sides of this operator will be considered in binary format and a logic AND would be performed on the bits of the same significance.
The int.MaxValue equals 2,147,483,647. The result of this operation is explained as below:
operation:
a = x & int.MaxValue;
result:
if (x >= 0) {a = x;}
if (x < 0) {a = x + 2,147,483,648;}
if x is non-negative then a = x;
if x is negative, then a = x + 2,147,483,648;
EDIT :
Logical Operations:
Logical operations like AND, OR, XOR, etc are defined to work on Boolean (logical) values. Boolean variables can have either 1 or 0 as their values. The result of AND operation between two logical variables will be 1 if and only if both the variables are equal to 1. This is shown below:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
Bitwise AND operator on numbers works using the basic AND operator. First the two numbers on the sides of operator are converted to binary format. If the number of digits in both numbers are not equal, zeros are added to the left side of the number with less number of digits to have the same number of digits for both numbers. Then the digits of the same significance are ANDed one by one the way explained above and the result of each operation will be written on the place with the same significance constructing the result. The bitwise and between 12 and 7 is shown below. 12 is demonstrated as 1100 in binary format and 7 is 0111.
12 = 0b1100
7 = 0b0111
12 & 7 = ?
1 1 0 0 &
0 1 1 1
----------
0 1 0 0 = 4
Related
I'm trying to learn C# right now and I'm using W3schools (website) in order to do so, but I came across some operators I dont completely understand.
I know that there are many questions asking what &= does in C# but I couldn't find anything relevant to my issue (dealing with numbers rather than True or False values)
From what I've gathered from online, the && operator is just an AND operator, and the & operator is just an AND operator but all conditions are checked
But when I searched for &= I can't find anything relevant to the way that its used on the W3Schools website, it shows the &= operator in use with numbers rather than boolean, and on the section that lets you try it out, I was receiving an output that I couldn't understand.
This is the link to the website page:
https://www.w3schools.com/cs/cs_operators_assignment.php
This is the link to the 'try it out' section where I got the code:
https://www.w3schools.com/cs/trycs.php?filename=demo_oper_ass7
Here's the code:
int x = 5;
x &= 3;
Console.WriteLine(x);
When I leave it as shown in the code above, I get an output of 1
When x = 10, output is 2
When x = 15, output is 3
When x = 20, output is 0
When x = 4329, output is 1
etc...
Please can somebody explain the &= operator, and if possible, the |=, ^= operators too?
I understand the use of all these operators by themselves when I searched them up however those understandings dont match with the usage of the ...= version shown on the website
Thanks alot
Let me preface this with the fact that I technically don't know C#, but I do know C, C++, and Java, and I also know that C# is a language in the C/C++ family (just like Java), so I would literally bet my life on this being correct in any and all of the languages mentioned.
Generally, for any binary operator _, the expression "a _= b" is (supposed to be considered -- C++ kind of messes with this, but that's besides the point) equivalent to "a = a _ b". As such,
a &= b is a = a & b
a |= b is a = a | b
a ^= b is a = a ^ b
All of those operators (&, |, ^) are, as you correctly recognized, boolean (as in, concerning only "true" and "false") operations. However, they are bitwise (as in binary numbers) boolean operations. In particular, the difference between the "logical" (as they are generally called, although the term is fairly misleading) operators and the "bitwise" operators is that the "logical" versions consider the veracity ("true-or-false-ness") of their operands as a whole, whereas the "bitwise" (remember that "bit" is short for "binary digit") versions consider each bit -- i.e. each digit of their operand when they are written in the binary system (Wiki "Positional notation" and "Binary number" for more information). Thus, && and || (there is no "logical" version of ^ in any C-like language I know) work on truth values as a whole -- which, in the case of Java and (almost certainly) C#, means type boolean/bool. For example, operator && indicates logical AND:
a
b
a && b
true
true
true
true
false
false
false
true
false
false
false
false
Analogously, operator || indicates logical OR. The bitwise operations, however, consider each binary digit of their operands (and since "binary" basically means "having two", this equates the whole "ones and zeroes" thing you see/hear everywhere), where (predictably) "0" indicates "false" and "1" indicates "true". Ergo, you can use the table above for "a & b" if only you replace all the "false" with "0" and all the "true" with "1". This explains why your program outputs what it does: In the initial example, you print 5 & 3, which, in binary notation, is 101 & 011. Ergo, in the result, only the digits where both operands have one (namely the last place) will be "1". Observe:
101
& 011
== 001
(If the binary notation is an issue, 5 = 22 + 20 = 4 + 1, and 3 = 21 + 20 = 2 + 1.) Since "1 AND 0" is "0" (leftmost digit), "0 AND 1" is "0" (middle digit), and "1 AND 1" is "1" (rightmost digit).
If it helps understand, consider the program as a mathematician would: Argue that any variable can have only one definition, and thus only one value. Thus, when you assign a new value, the system would actually have to intoduce a "new" ("hidden") variable for the new definition, so your
x = 5
x = x & 3
print x
is actually
x0 = 5
x1 = x0 & 3
print x1 // not a math thing, just here for completeness
(This is actually how the compiler views your program; Wiki "Static single-assignment form" if interested.)
The bottom line is: If you have a number ("more than one") of boolean values (true or false), you can combine them into an integer value (byte/sbyte/short/ushort/int/uint/long/ulong) by assigning one binary place for each boolean value and then use boolean operations (& → AND, | → OR, ^ → XOR) to combine all of the boolean values at once. Consider (and note again that I don't actually know C# per se, so I'm pretty much winging this based on some Googling; there might be some issues, but I trust the principle becomes clear) the definitions:
static readonly int CHEAP = 0; // binary: 000
static readonly int EXPENSIVE = 1; // binary: 001
static readonly int LIGHT = 0; // binary: 000
static readonly int HEAVY = 2; // binary: 010
static readonly int WEAK = 0; // binary: 000
static readonly int POWERFUL = 4; // binary: 100
// and now, the combinations:
static readonly int GENERIC = 0; // binary: 000 (cheap, light, weak)
static readonly int LUXURY = 3; // binary: 011 (expensive, heavy, ?)
static readonly int MUSCLE = 7; // binary: 111 (expensive, heavy, powerful)
static readonly int PONY = 6; // binary: 011 (cheap, heavy, powerful)
Here, we consider the following veracities:
The 20 (i.e. rightmost binary) place indicates "expensive".
The 21 (i.e. middle binary) place indicates "heavy".
The 22 (i.e. leftmost binary) place indicates "powerful".
Now, we can put all three boolean values into an integer (would fit into a byte, but usually people use int):
class Car {
readonly string name;
readonly int traits;
Car(string name, int traits) {
this.name = name;
this.traits = traits;
}
bool isGeneric() {
// if and only if all veracities are "false"
// should be the same as "return traits == GENERIC", but somebody might set traits to > 7
// note that EXPENSIVE | HEAVY | POWERFUL == 7, so we only consider the three "defined" bools
return (traits & (EXPENSIVE | HEAVY | POWERFUL)) == GENERIC;
}
bool isLuxury() {
// if and only if the two veracities dictated by LUXURY match, with no regard for power
return (traits & LUXURY) == LUXURY;
}
bool isMuscle() {
// if and only if all veracities are "true"
// should be the same as "return traits == MUSCLE", but somebody might set traits to > 7
return (traits & MUSCLE) == MUSCLE;
}
bool isPony() {
// if and only if all three veracities dictated by PONY match
// note that EXPENSIVE | HEAVY | POWERFUL == 7, so we only consider the three "defined" bools
// also note that this requires that EXPENSIVE not be set,
// i.e. "== PONY" is equivalent to "== (HEAVY | POWERFUL)" and "== (CHEAP | HEAVY | POWERFUL)"
return (traits & (EXPENSIVE | HEAVY | POWERFUL)) == PONY;
}
}
Then, we can do something like:
// "PONY" could also be written as "CHEAP | HEAVY | POWERFUL" or "HEAVY | POWERFUL"
Car fordMustang = new Car("Ford Mustang", PONY);
(And yes, I drive a Mustang. :P)
I have a 3 element enum, it defines one of three contexts, for example red, green, or blue. This enum is used in a loop with millions of iterations, for example, pixel many. The fields are currently one int apart, the default. Given a desired production order of R,G,B,R,G,B..., I have currently resorted to checking if the value is currently B, thus assigning it to R, otherwise incrementing the value.
private enum CHANNEL_CONTEXT {RED, GREEN, BLUE} //here is a sample enum
//here is a sample loop with the relevant construct
CHANNEL_CONTEXT current = CHANNEL_CONTEXT.RED;
while(condition)
{
use current;
//...
if(current == CHANNEL_CONTEXT.BLUE)
current = CHANNEL_CONTEXT.RED
else
current+=1;
}
Is there a way to wrap a 3 field enum with a single operation, such that no branch is required to determine if it is time to wrap. I know modulus(%) fits the bill, but my motivation is a performance based one, and I'd break even at best with such an expensive operation(testing corroborated, but not exhaustively).
To put my agenda in perspective, if i had 256 relevant fields, I could create a byte based enum, and increment with impunity and intended overflow. Alas, I only have three, and I cant think of a way to manipulate any integral primitive in a way that three values are produced cyclically, using a lightweight ALU operation,(+,-,&,^,|,<<..etc). I also wouldn't have been able to think of a way to swap bits with no temporary using such operations, but there is a rarely practical but possible way to do so.
Can someone guide me to a way to distribute 3 integral enum values such that they are traversable periodically, with no branch required, and no division based operators used(like modulus)?
While it sounds very unlikely that you can beat x = (x + 1) % 3 you can try to use mapping table:
var map = new[]{1,2,0};
x = map[x];
You probably would need to wrap that in unsafe to remove boundary checks on array access.
If you really set on bit manipulation irrespective of readability of the code - the table of converting numbers you are interested in is small enough to build manually for each bit and then combine.
Truth table:
Source Result
Bit2 Bit1 Bit2 Bit1
0 0 0 1
0 1 1 0
1 0 0 0
1 1 x x
As you can see the values we are interested in only produce 2 non-zero bits so resulting expression will be very simple - one case for 1 for lower bit and one case for higher bit (assuming values never fall out of the range 0-2 (which is safe if this is the only transformation).
var b1 = (x & 1) >> 0; // extract lower bit 0
var b2 = (x & 2) >> 1; // extract higher bit 1
// only care of cases when pair of bits results in 1
var resultBit1 = 1 & (~b1 & ~b2); // 00 -> x1, other cases is 0
var resultBit2 = (1 & (b1 & ~b2)) << 1; // 01 -> 1x, other cases is 0
x = resultBit1 | resultBit2;
Or inlining all into one unreadable line:
x = 1 & ~(x | x >> 1) | 2 & (x & 1 & ~x >> 1) << 1;
Any fast way to check if two doubles have the same sign? Assume the two doubles cannot be 0.
Potential solutions:
a*b > 0: One floating-point multiply and one comparison.
(a>0) == (b>0): Three comparisons.
Math.Sign(a) == Math.Sign(b): Two function calls and one comparison.
Speed comparison:
It's about what you'd expect (see experimental setup at the bottom):
a*b > 0: 0.42 ± 0.02s
(a>0) == (b>0): 0.49 ± 0.01s
Math.Sign(a) == Math.Sign(b): 1.11 ± 0.9s
Important notes:
As noted by greybeard in the comments, method 1 is susceptible to problems if the values multiply to something smaller than Double.Epsilon. Unless you can guarantee that the multiple is always larger than this, you should probably go with method 2.
Experimental setup:
The following code was run 16 times on http://rextester.com/.
public static void Main(string[] args)
{
double a = 1e-273;
double b = a;
bool equiv = false;
for(int i=0; i<100000000; ++i) {
equiv = THE_COMPARISON;
b += a;
}
//Your code goes here
Console.WriteLine(equiv);
}
The simplest and fastest way for IEEE 754 I know of is just using XOR on the MSB bits of both numbers. Here is a small C# example (note the inlining to avoid the function overhead):
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe static bool fpu_cmpsign(double a, double b)
{
byte* aa;
byte* bb;
aa = (byte*)(&a); // points to the a as 8bit integral type
bb = (byte*)(&b); // points to the b as 8bit integral type
return ((aa[7] ^ bb[7]) & 128) != 128;
}
Here result of +/- numbers combinations:
a b result
- - 1
- + 0
+ - 0
+ + 1
The idea is simple. The sign is stored in the highest bit (MSB) and XOR returns 1 for non equal bits so XOR the MSB of booth numbers together and negate the output. the [7] is just accessing highest BYTE of the double as 8 bit integral type so I can use CPU ALU instead FPU. If your platform has reversed order of BYTES then use [0] instead (MSByte first vs. LSByte first).
So what you need is just 3x 8 bit XORs for comparison and negation and 1x 8bit AND for extracting sign bit result only.
You can use unions instead of pointers and also use native bit-width for your platform to get best performance.
You could use:
if (copysign(x, y) == x)
I was wondering how the following enum masking works
If I have an Enum structure
public enum DelMask
{
pass = 1,
fail = 2,
abandoned = 4,
distinction = 8,
merit = 16,
defer = 32,
}
I have seen the following code
int pass = 48;
if ((pass & (int)DelMask.defer) > 0)
//Do something
else if ((pass & (int)DelMask.merit ) > 0)
//Do something else
I am wondering can anyone help me figure out how which block will get executed?
Basic bit logic at work here. The integer 48 ends like this in binary:
0011 0000
Defer, 32, is:
0010 0000
Merit, 16, is:
0001 0000
Now when you perform a logical AND (&), the resulting bits are set where they are both in the input:
pass & (int)DelMask.defer
0011 0000
0010 0000
========= &
0010 0000
The result will be 16, so ((pass & (int)DelMask.defer) > 0) will evaluate to true. Both if's will evaluate to true in your example because both flags are present in the input. The second one won't be evaluated though, because it's an else if.
Both are correct so the first will get executed.
16 is 10000
32 is 100000
48 is 16+32 so it is 110000
10000 & 110000 is 10000
100000 & 110000 is 100000
Both are bigger than zero.
48 = 16 (merit) + 32 (defer).
Thus pass & (int)DelMask.defer evaluates to 32, so the first block runs.
If that wasn't the case, pass & (int)DelMask.merit evaluates to 16, so the second block would run if it got that far.
This only works because the values in the enum are all different powers of 2 and thus correspond to independent bits in the underlying int. This is what is known as a bit flags enum.
First, it should be int pass = 48;
Basically this code checks whether a bit is set in a binary representation of the number. Each & operation should produce a result with all zeroes and one on the place where it is in the mask. for instance:
48: 110000
defer = 32: 100000
______
& 100000
So you can use this code:
int pass = 48;
if ((pass & (int)DelMask.defer) == (int)DelMask.defer)
//Do something
else if ((pass & (int)DelMask.merit ) == (int)DelMask.merit)
//Do something else
Well you need to think of those numbers as binary. I'll use the d suffix to show decimal notation and b suffix for binary notation.
enum values:
01d = 000001b
02d = 000010b
04d = 000100b
08d = 001000b
16d = 010000b
32d = 100000b
pass value:
48d = 110000b
Now the & is the bit-wise AND operator. Which means that if c = a&b, the nth bit in c will be 1 if and only if the nth bit is 1 in both a and b.
So:
16d & 48d = 010000b = 16d > 0
32d & 48d = 100000b = 32d > 0
As you see, your number 48d "matches" with both 16d and 32d. That is why this kind of enums is generally described as a "flag" enum: you can have with one integer the value of several "flags".
As for your code, the first if operator will be verified, which means that you will enter it and "Do something". You will not "Do something else".
Generally in C#, we use the [Flags] attribute for flag enums, which allows not actually writing the decimal values for the enum members. As usual, the example in the MSDN is useless so I'll refer to this SO question for more details about how to use it (note that to know if a value x has a flag f set, you can either do x & f == f or x | f == x, but the usage seems to be to generally use the latter one).
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Finding Byte logarithm
I am implemeting the SAFER+ algorithm, this algorithm uses 16 bytes byte-array and performs the operations on Bytes.
The first phase includes XOR and ADDITON funciton with the Subkeys, no problems to mention here.
The second phase is the nonlinear layer which uses POWER and LOGARITHMS on the bytes' values, the problem here is when we take the log "to base 45" of the Value, the result is a floating point double, and this value should be passed to phase 3 as a byte to be handled in the same way of the phase one.
Create an exponentiation table that looks like this:
exp | log
----+----
0 | 1
1 | 45
2 | 226
3 | 147
... | ...
128 | 0
... | ...
255 | 40
---------
The "log" values are 45exp % 257. You'll need an arbitrary precision arithmetic library with a modPow function (raise a number to a power, modulo some value) to build this table. You can see that the value for "exp" 128 is a special case, since normally the logarithm of zero is undefined.
Compute the logarithm of a number by finding the it in the "log" column; the value in the "exp" column of that row is the logarithm.
Here's a sketch of the initialization:
BigInteger V45 = BigInteger.valueOf(45);
BigInteger V257 = BigInteger.valueOf(257);
int[] exp = new int[256];
int[] log = new int[256];
for (int idx = 0; idx < 256; ++idx)
exp[idx] = V45.modPow(BigInteger.valueOf(idx), V257).intValue() % 256;
for (int idx = 0; idx < 256; ++idx)
log[exp[idx]] = idx;
With this setup, for example, log45(131) = log[131] = 63, and 4538 = exp[38] = 59.
You can do this with a Linq expression as follows
inputBytes.Select(b => b == 0 ? (byte)128 : Convert.ToByte(System.Math.Log(Convert.ToDouble(b), 45))).ToArray();
But this will truncate the double, as it has to do...
Edited after looking at SAFER+, it uses the convention that Log45(0)=128 to avoid numeric overflow.