Combine two ulong values and convert it to byte array - c#

I have a problem that I can't solve whole day. I'm new in C# and I'm asking you tog ive me a hand.
I have two ulong values. I need combine their binary representations and get 16 bytes value. I know C# does not support 128 bit types. But I also do not need to hold this value in variable. I need to convert this value to byte array.
I tried to combine values like this:
long a = ((long)b << 64) + (long)c;
and after convert to byte array with BitConverter.
But I realize that this is incorrect, because size of long values is 8 byte.
I don't want to create a 128 type to get result.
So is there a way to combine and add to byte array directly?
Thanks

Microsoft C# supports integers of arbitrary length, using BigInteger. You could combine your two values, such as in the example you have given, like so:
BigInteger a = b;
a <<= 64;
a += c;
However, as you've indiciated you don't need to store this value. Before you mention, yes, I am aware of endianness. There's machine-dependent endianness and over-the-wire endianness. We should not try to produce any machine-dependent endianness... The way we can produce over-the-wire endianness in the languages I'm most familiar with is using the right-shift and modulo operators, at least for unsigned types. Signed types introduce the complication of encoding the sign, but here's an example I think you might benefit from:
byte[] array = { (byte)(b >> 56), (byte)(b >> 48), (byte)(b >> 40), (byte)(b >> 32),
(byte)(b >> 24), (byte)(b >> 16), (byte)(b >> 8), (byte)(b ),
(byte)(c >> 56), (byte)(c >> 48), (byte)(c >> 40), (byte)(c >> 32),
(byte)(c >> 24), (byte)(c >> 16), (byte)(c >> 8), (byte)(c ) };

If I run this:
var x = (ulong)1;
var y = (ulong)2;
var result =
BitConverter.GetBytes(x)
.Concat(BitConverter.GetBytes(y))
.ToArray();
I get this:
Is that what you want?

I guess its homework?
You can represent your terms, the ulongs a and b as byte arrays.
Afterwards you may create a new byte array c for the sum.
For Each byte go bit by bit and just do a normal two's complement binary addition, remember the carry bit from byte to byte.
If the last byte has carry bit then you should throw "ulong addition overflow exception" of some kind.

Related

How can I store 4 8 bit coordinates into one integer (C#)?

Lets say I have the following four variables: player1X, player1Y, player2X, player2Y. These have, for example, respectively the following values: 5, 10, 20, 12. Each of these values is 8 bits at max and I want to store them into one integer (32 bits), how can I achieve this?
By doing this, I want to create a dictionary, keeping count of how often certain states have happened in the game. For example, 5, 10, 20, 12 is one state, 6, 10, 20, 12 would be another.
You can use BitConverter
To get one Integer out of 4 bytes:
int i = BitConverter.ToInt32(new byte[] { player1X, player1Y, player2X, player2Y }, 0);
To get the four bytes out of the integer:
byte[] fourBytes = BitConverter.GetBytes(i);
To "squeeze" 4 8 bits value in a 32 bit space, you need to "shift" the bits for your various values, and add them together.
The opposite operations is to "unshift" and use some modulo to get the individual numbers you need.
Here is an alterantive:
Make a struct with defined packing. Expose:
The int32 and all 4 bytes at the same time
Make sure the apcking overlaps (i.e. int starts at 0, byte variables at 0, 1,2,3
Done.
And you can easily access and work with them WITHOUT a bitconverter et al and never have to define an array, which is expensive jsut to throw it away.
You can place the values by shifting to the apropriate offset
Example:
// Composing
byte x1 = ...;
byte x2 = ...;
byte x3 = ...;
byte x4 = ...;
uint x = x1 | (x2 << 0x8) | (x3 << 0x10) | (x4 << 0x18);
// Decomposing
uint x = ...;
byte x1 = x & 0xFF;
byte x2 = (x >> 0x8) & 0xFF;
byte x3 = (x >> 0x10) & 0xFF;
byte x4 = (x >> 0x18) & 0xFF;

Concatenating bytes into integer or short preserving sign

I know I can extract bytes from int like this:
bytes[] IntToBytes(int i)
{
return new byte [] {(byte) ((i >> 8) & 0xff), (byte) (i & 0xff)};
}
which I subsequently send as part of a serial transmission. But can I do the reverse, after receiving a sequence of bytes, reconstruct the original data, preserving the sign. Currently, I do this, but it feels a bit over the top:
int BytesToInt( byte hi, byte lo)
{
return ((hi << 24) | (lo << 16)) >> 16;
}
Is there another way or a better way? Does it make a difference if I know I am ultimately dealing with signed 16-bit data only?
You're working with signed 16-bit data only. So why are you passing (and returning) an int and not a short? You're throwing the sign information away, so it will not actually work for negative numbers. Instead, use short and you'll be fine - and the extra type information will make your code safer.
byte[] ShortToBytes(short i)
{
return new byte [] {(byte) ((i >> 8) & 0xff), (byte) (i & 0xff)};
}
short BytesToShort(byte hi, byte lo)
{
return unchecked((short)((hi << 8) | lo));
}
The main benefit (apart from being clearer and actually working) is that you can no longer pass an invalid value to the method. That's always good :)
Oh, and I'd recommend keeping the interface symmetric - BytesToShort should also take a byte[] (or some other structure that has the two bytes).

Fastest way to XOR two specific bit indexes in two bytes

This is in C#. I was hoping I could do something like the following.
byte byte1 = 100;
byte byte2 = 100;
byte1[1] = byte1[1] ^ byte2[6]; // XOR bit at index 1 against bit at index 6
However, I am currently stuck at:
if ((byte2 ^ (byte)Math.Pow(2, index2)) < byte2)
byte1 = (byte)(byte1 ^ (byte)Math.Pow(2, index1));
Is there a faster way, possibly something similar to what I typed at the top?
Edit:
I had never heard of any of the bitwise operators other than XOR. That's why the original solution had the bizarre Math.Pow() calls. I've already improved my solution considerably according to my benchmarking of millions of loop iterations. I'm sure I'll get it faster with more reading. Thanks to everybody that responded.
byte2 = (byte)(byte2 << (7 - index2));
if (byte2 > 127)
{
byte buffer = (byte)(1 << index1);
byte1 = (byte)(byte1 ^ buffer);
}
Bytes are immutable, you can't change a bit of the byte as if it was an array. You'd need to access the bits through masks (&) and shifts (<< >>), then create a new byte containing the result.
// result bit is the LSB of r
byte r = (byte)((byte1 >> 1 & 1) ^ (byte2 >> 6 & 1));
The specific mask 1 will erase any bit except the right most (LSB).

C# convert hex into ip

i have hex values in the format of 4a0e94ca etc, and i need to convert them into IP's, how can i do this in C# ?
If the values represent IPv4 addresses you can use the long.Parse method and pass the result to the IPAddress constructor:
var ip = new IPAddress(long.Parse("4a0e94ca", NumberStyles.AllowHexSpecifier));
If they represent IPv6 addresses you should convert the hex value to a byte array and then use this IPAddress constructor overload to construct the IPAddress.
Well, take the format of an IP in this form:
192.168.1.1
To get it into a single number, you take each part, OR it together, while shifting it to the left, 8 bits.
long l = 192 | (168 << 8) | (1 << 16) | (1 << 24);
Thus, you can reverse this process for your number.
Like so:
int b1 = (int) (l & 0xff);
int b2 = (int) ((l >> 8) & 0xff);
int b3 = (int) ((l >> 16) & 0xff);
int b4 = (int) ((l >> 24) & 0xff);
-- Edit
Other posters probably have 'cleaner' ways of doing it in C#, so probably use that in production code, but I do think the way I've posted is a nice way to learn the format of IPs.
Check C# convert integer to hex and back again
var ip = String.Format("{0}.{1}.{2}.{3}",
int.Parse(hexValue.Substring(0, 2), System.Globalization.NumberStyles.HexNumber),
int.Parse(hexValue.Substring(2, 2), System.Globalization.NumberStyles.HexNumber),
int.Parse(hexValue.Substring(4, 2), System.Globalization.NumberStyles.HexNumber),
int.Parse(hexValue.Substring(6, 2), System.Globalization.NumberStyles.HexNumber));

What is the best way to combine two uints into a ulong in c#

What is the best way to combine two uints into a ulong in c#, setting the high/low uints.
I know bitshifting can do it, but I don't know the syntax, or there maybe other APIs to help like BitConverter, but I don't see a method that does what I want.
ulong mixed = (ulong)high << 32 | low;
The cast is very important. If you omit the cast, considering the fact that high is of type uint (which is 32 bits), you'll be shifting a 32 bit value 32 bits to the left. Shift operators on 32 bit variables will use shift stuff by right-hand-side mod 32. Effectively, shifting a uint 32 bits to the left is a no-op. Casting to ulong prevents this.
Verifying this fact is easy:
uint test = 1u;
Console.WriteLine(test << 32); // prints 1
Console.WriteLine((ulong)test << 32); // prints (ulong)uint.MaxValue + 1
ulong output = (ulong)highUInt << 32 + lowUInt
The << and >> operators bitshift to the left (higher) and right (lower), respectively. highUInt << 32 is functionally the same as highUInt * Math.Pow(2, 32), but may be faster and is (IMO) simpler syntax.
You have to convert the highInt to a ulong before you bitshift:
ulong output = highInt;
output = output << 32;
output += lowInt;
Encoding:
ulong mixed = (ulong)hi << 32 | lo;
Decoding:
uint lo = (uint)(mixed & uint.MaxValue);
uint hi = (uint)(mixed >> 32);

Categories

Resources