I have 10 bytes - 4 bytes of low order, 4 bytes of high order, 2 bytes of highest order - that I need to convert to an unsigned long. I've tried a couple different methods but neither of them worked:
Try #1:
var id = BitConverter.ToUInt64(buffer, 0);
Try #2:
var id = GetID(buffer, 0);
long GetID(byte[] buffer, int startIndex)
{
var lowOrderUnitId = BitConverter.ToUInt32(buffer, startIndex);
var highOrderUnitId = BitConverter.ToUInt32(buffer, startIndex + 4);
var highestOrderUnitId = BitConverter.ToUInt16(buffer, startIndex + 8);
return lowOrderUnitId + (highOrderUnitId * 100000000) + (highestOrderUnitId * 10000000000000000);
}
Any help would be appreciated, thanks!
As the comments indicate, 10 bytes will not fit in a long (which is a 64-bit data type - 8 bytes). However, you could use a decimal (which is 128-bits wide - 16 bytes):
var lowOrderUnitId = BitConverter.ToUInt32(buffer, startIndex);
var highOrderUnitId = BitConverter.ToUInt32(buffer, startIndex + 4);
var highestOrderUnitId = BitConverter.ToUInt16(buffer, startIndex + 8);
decimal n = highestOrderUnitId;
n *= UInt32.MaxValue;
n += highOrderUnitId;
n *= UInt32.MaxValue;
n += lowOrderUnitId;
I've not actually tested this, but I think it will work...
As has been mentioned, a ulong isn't large enough to hold 10 bytes of data, it's only 8 bytes. You'd need to use a Decimal. The most efficient way (not to mention least code) would probably be to get a UInt64 out of it first, then add the high-order bits:
ushort high = BitConverter.ToUInt16(buffer, 0);
ulong low = BitConverter.ToUInt64(buffer, 2);
decimal num = (decimal)high * ulong.MaxValue + high + low;
(You need to add high a second time because otherwise you'd need to multiply by the value ulong.MaxValue + 1, and that's a lot of annoying casting and parentheses.)
Related
I use the biginteger class whose source , and I want to generate a biginteger number between two values min and max randomly so i used this method found on stackoverflow :
public BigInteger getRandom(int n)
{
var rng = new RNGCryptoServiceProvider();
byte[] bytes = new byte[n / 8];
rng.GetBytes(bytes);
return new BigInteger(bytes);
}
But I can not generate numbers between min and max because the parameters of this function represent the number of bits, can someone help me, thank you in advance!
min and max are also a biginteger.
Try this one:
// max exclusive (not included!)
public static BigInteger GetRandom(RNGCryptoServiceProvider rng, BigInteger min, BigInteger max)
{
// shift to 0...max-min
BigInteger max2 = max - min;
int bits = max2.bitCount();
// 1 bit for sign (that we will ignore, we only want positive numbers!)
bits++;
// we round to the next byte
int bytes = (bits + 7) / 8;
int uselessBits = bytes * 8 - bits;
var bytes2 = new byte[bytes];
while (true)
{
rng.GetBytes(bytes2);
// The maximum number of useless bits is 1 (sign) + 7 (rounding) == 8
if (uselessBits == 8)
{
// and it is exactly one byte!
bytes2[0] = 0;
}
else
{
// Remove the sign and the useless bits
for (int i = 0; i < uselessBits; i++)
{
//Equivalent to
//byte bit = (byte)(1 << (7 - (i % 8)));
byte bit = (byte)(1 << (7 & (~i)));
//Equivalent to
//bytes2[i / 8] &= (byte)~bit;
bytes2[i >> 3] &= (byte)~bit;
}
}
var bi = new BigInteger(bytes2);
// If it is too much big, then retry!
if (bi >= max2)
{
continue;
}
// unshift the number
bi += min;
return bi;
}
}
There are some comments that explain a little how it work.
I'm playing around with Source RCON Protocol, but I'm having issues converting a strings to byte array successfully.
Original Code (VB.NET) + Pastebin: http://pastebin.com/4BkbTRfD
Private Function RCON_Command(ByVal Command As String,
ByVal ServerData As Integer) As Byte()
Dim Packet As Byte() = New Byte(CByte((13 + Command.Length))) {}
Packet(0) = Command.Length + 9 'Packet Size (Integer)
Packet(4) = 0 'Request Id (Integer)
Packet(8) = ServerData 'SERVERDATA_EXECCOMMAND / SERVERDATA_AUTH (Integer)
For X As Integer = 0 To Command.Length - 1
Packet(12 + X) = System.Text.Encoding.Default.GetBytes(Command(X))(0)
Next
Return Packet
End Function
My current code in C# + Pastebin: http://pastebin.com/eVv0nZCf
byte[] RCONCommand(string cmd, int serverData)
{
int packetSize = cmd.Length + 12;
byte[] byteList = new byte[packetSize];
byteList[0] = (byte)packetSize;
byteList[4] = 0;
byteList[8] = (byte)serverData;
for(int X = 0; X < cmd.Length; X++)
{
byteList[12 + X] = Encoding.ASCII.GetBytes(cmd)[X];
}
return byteList;
}
When I use Encoding.ASCII.GetString(RCONCommand("Word", 3)); the result will be square mark. I tried with Encoding.UTF8.GetString() too, but same result.
Packet structure can be found here: https://developer.valvesoftware.com/wiki/Source_RCON_Protocol#Basic_Packet_Structure
I don't just figure it out what I've done wrong, because I'm not even a familiar with bytes and such. PS. The example applications that has been posted in C# for Source RCON Protocol documentation are garbled, because people is using so much OOP and creates millions of class files so I cannot even find the correct stuff.
A byte is 8 bits. That means that a value such as Size, which according to the spec is a 32-bit little-endian unsigned integer, will require 4 bytes (32 รท 8 = 4).
To fit 32 bits of information into four bytes, you have to split it up. Think of this as dividing a four-digit number into four strings, one for each digit. Except we're working in binary, so it's a little more complicated. We have to do some bit shifting and masking to get just the bits we want into each "string."
The spec calls for little-endian, sothe least significant bytes come first; this takes some getting used to if you haven't done this before.
byte[0] = size && 0xFF;
byte[1] = (size >> 8) && 0xFF;
byte[2] = (size >> 16) && 0xFF;
byte[3] = (size >> 24) && 0xFF;
If you want to rely on the CLR, you can use BitConverter, although it's platform dependent, and not all platforms are little-endian.
var tmp = BitConverter.GetBytes(size);
if (BitConverter.IsLittleEndian)
{
byte[0] = tmp[0];
byte[1] = tmp[1];
byte[2] = tmp[2];
byte[3] = tmp[3];
}
else //in case you are running on a bigendian machine like a Mac
{
byte[0] = tmp[3];
byte[1] = tmp[2];
byte[2] = tmp[1];
byte[3] = tmp[0];
}
I want to convert an int to a byte[2] array using BCD.
The int in question will come from DateTime representing the Year and must be converted to two bytes.
Is there any pre-made function that does this or can you give me a simple way of doing this?
example:
int year = 2010
would output:
byte[2]{0x20, 0x10};
static byte[] Year2Bcd(int year) {
if (year < 0 || year > 9999) throw new ArgumentException();
int bcd = 0;
for (int digit = 0; digit < 4; ++digit) {
int nibble = year % 10;
bcd |= nibble << (digit * 4);
year /= 10;
}
return new byte[] { (byte)((bcd >> 8) & 0xff), (byte)(bcd & 0xff) };
}
Beware that you asked for a big-endian result, that's a bit unusual.
Use this method.
public static byte[] ToBcd(int value){
if(value<0 || value>99999999)
throw new ArgumentOutOfRangeException("value");
byte[] ret=new byte[4];
for(int i=0;i<4;i++){
ret[i]=(byte)(value%10);
value/=10;
ret[i]|=(byte)((value%10)<<4);
value/=10;
}
return ret;
}
This is essentially how it works.
If the value is less than 0 or greater than 99999999, the value won't fit in four bytes. More formally, if the value is less than 0 or is 10^(n*2) or greater, where n is the number of bytes, the value won't fit in n bytes.
For each byte:
Set that byte to the remainder of the value-divided-by-10 to the byte. (This will place the last digit in the low nibble [half-byte] of the current byte.)
Divide the value by 10.
Add 16 times the remainder of the value-divided-by-10 to the byte. (This will place the now-last digit in the high nibble of the current byte.)
Divide the value by 10.
(One optimization is to set every byte to 0 beforehand -- which is implicitly done by .NET when it allocates a new array -- and to stop iterating when the value reaches 0. This latter optimization is not done in the code above, for simplicity. Also, if available, some compilers or assemblers offer a divide/remainder routine that allows retrieving the quotient and remainder in one division step, an optimization which is not usually necessary though.)
Here's a terrible brute-force version. I'm sure there's a better way than this, but it ought to work anyway.
int digitOne = year / 1000;
int digitTwo = (year - digitOne * 1000) / 100;
int digitThree = (year - digitOne * 1000 - digitTwo * 100) / 10;
int digitFour = year - digitOne * 1000 - digitTwo * 100 - digitThree * 10;
byte[] bcdYear = new byte[] { digitOne << 4 | digitTwo, digitThree << 4 | digitFour };
The sad part about it is that fast binary to BCD conversions are built into the x86 microprocessor architecture, if you could get at them!
Here is a slightly cleaner version then Jeffrey's
static byte[] IntToBCD(int input)
{
if (input > 9999 || input < 0)
throw new ArgumentOutOfRangeException("input");
int thousands = input / 1000;
int hundreds = (input -= thousands * 1000) / 100;
int tens = (input -= hundreds * 100) / 10;
int ones = (input -= tens * 10);
byte[] bcd = new byte[] {
(byte)(thousands << 4 | hundreds),
(byte)(tens << 4 | ones)
};
return bcd;
}
maybe a simple parse function containing this loop
i=0;
while (id>0)
{
twodigits=id%100; //need 2 digits per byte
arr[i]=twodigits%10 + twodigits/10*16; //first digit on first 4 bits second digit shifted with 4 bits
id/=100;
i++;
}
More common solution
private IEnumerable<Byte> GetBytes(Decimal value)
{
Byte currentByte = 0;
Boolean odd = true;
while (value > 0)
{
if (odd)
currentByte = 0;
Decimal rest = value % 10;
value = (value-rest)/10;
currentByte |= (Byte)(odd ? (Byte)rest : (Byte)((Byte)rest << 4));
if(!odd)
yield return currentByte;
odd = !odd;
}
if(!odd)
yield return currentByte;
}
Same version as Peter O. but in VB.NET
Public Shared Function ToBcd(ByVal pValue As Integer) As Byte()
If pValue < 0 OrElse pValue > 99999999 Then Throw New ArgumentOutOfRangeException("value")
Dim ret As Byte() = New Byte(3) {} 'All bytes are init with 0's
For i As Integer = 0 To 3
ret(i) = CByte(pValue Mod 10)
pValue = Math.Floor(pValue / 10.0)
ret(i) = ret(i) Or CByte((pValue Mod 10) << 4)
pValue = Math.Floor(pValue / 10.0)
If pValue = 0 Then Exit For
Next
Return ret
End Function
The trick here is to be aware that simply using pValue /= 10 will round the value so if for instance the argument is "16", the first part of the byte will be correct, but the result of the division will be 2 (as 1.6 will be rounded up). Therefore I use the Math.Floor method.
I made a generic routine posted at IntToByteArray that you could use like:
var yearInBytes = ConvertBigIntToBcd(2010, 2);
static byte[] IntToBCD(int input) {
byte[] bcd = new byte[] {
(byte)(input>> 8),
(byte)(input& 0x00FF)
};
return bcd;
}
I currently have a function [C#] which takes a byte[] and an alignment to set it to, but during encryption, an error is thrown every once in awhile.
private byte[] AlignByteArray(byte[] content, int alignto)
{
long thelength = content.Length - 1;
long remainder = 1;
while (remainder != 0)
{
thelength += 1;
remainder = thelength % alignto;
}
Array.Resize(ref content, (int)thelength);
return content;
}
Does anyone see any issues with the function? I'm getting errors that the content size is not valid during AES encryption, suggesting that it is not padding right.
Here's a simple solution:
private static void PadToMultipleOf(ref byte[] src, int pad)
{
int len = (src.Length + pad - 1) / pad * pad;
Array.Resize(ref src, len);
}
Are you sure it's 0x16 and not 16? (I thought it was 16 so I'm assuming that).
Edit: Any decent compiler should turn (x / 16) into (x >> 4).
int length = 16 * ((content.Length + 15) / 16);
Array.Resize(ref content, length);
Edit 2: For general purpose:
int length = alignment * ((content.Length + alignment - 1) / alignment);
Array.Resize(ref content, length);
I have a 1-dimensional float array of root mean square values, each calculated with the same window length. Let's say
RMS = {0, 0.01, 0.4, ... }
Now the RMS for a larger window, which can be represented as a range of the original windows, can be calculated as the RMS of the "participating" RMS values from RMS[i] to RMS[i + len]. Here len is the length of the larger window divided by the lenght of the original windows.
I'd like to create a rolling window. I want
rollingRMS[0] = RMS from 0 to len
...
rollingRMS[n] = RMS from n to len+n
calculated as efficiently as possible. I know this isn't very hard to crack, but does anyone have ready code for this?
EDIT: I asked for sample code, so I guess it would be decent to provide some. The following is based on pierr's answer and is written in C#. It's a bit different from my original question as I realized it would be nice to have the resulting array to have the same size as the original and to have the windows end at each element.
// The RMS data to be analysed
float[] RMS = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// The resulting rolling RMS values
float[] rollingRMS = new float[RMS.Length];
// Window lenght
int len = 3;
// Calculate: rollingRMS will hold root mean square from windows which end at
// each respective sample in the RMS array. For the first len samples the input
// will be treated as zero-padded
for (int i = 0; i < RMS.Length; i++)
{
if (i == 0)
rollingRMS[i] = (float)Math.Sqrt((RMS[i] * RMS[i] / len));
else if (i < len)
rollingRMS[i] = (float)Math.Sqrt(
( RMS[i] * RMS[i] +
len * (rollingRMS[i - 1] * rollingRMS[i - 1])
) / len);
else
rollingRMS[i] = (float)Math.Sqrt(
( len * (rollingRMS[i - 1] * rollingRMS[i - 1]) +
RMS[i] * RMS[i] -
RMS[i - len] * RMS[i - len]
) / len);
}
I am not sure that I have understood your problem correctly. But let me have a try.
a=[1,2,3,4,5,6,7,8,9,10]
LEN = 3
SquareOfRollingRMS[0] = (a[0]^2 + a[1]^2 + a[2]^2 ) / LEN
SquareOfRollingRMS[1] = ( a[1]^2 + a[2]^2 + a[3]^2 ) / LEN
It's not difficult to notice that:
SquareOfRollingRMS[i] = RollingRMS[i-1] * LEN - a[i-1]^2 + a[i+LEN-1]^2
RollingRMS[i] = SqurefOfRollingRMS[i]^(1/2)
Doing it this way ,you are avoiding recaculating the overlap windows.
EDIT:
You can save some divide and multiply operation by moving LEN to the left side of the equations. This might speed up a lot as dividing is usually relatively slow.
LEN_by_SquareOfRollingRMS[0] = (a[0]^2 + a[1]^2 + a[2]^2)
LEN_by_SquareOfRollingRMS[i] = LEN_by_RollingRMS[i-1] - a[i-1]^2 + a[i+LEN-1]^2