i have array of byte, i want to find 32-bit unsigned fixed-point number (16.16) ) use c# and
the output must 44100
array of byte:
byte[] m = new byte[4] {172,68,0,0}
Console.WriteLine(" sample rate {0}", BitConverter.ToInt32(m, 0));
The output is 17580. This is wrong: it should be 44100
how to convert it to (a 32-bit unsigned fixed-point number (16.16) ) use c# ??
.Net doesn't have a built-in 32-bit fixed point data type, but you could store the result pretty easily in a double.
This is not quite as efficient or elegant as what you're probably looking for, but you could do something like this to convert your byte array to a double:
byte[] m = new byte[4] { 172, 68, 0, 0 };
double[] magnitude = new[] { 256.0, 1.0, 1.0/256.0, 1.0/65536.0 };
double i = m.Zip(magnitude, (x, y) => x * y).Sum(); // 44100.0
Alternatively, if you change the way you store the bits like this:
byte[] m = new byte[4] { 0, 0, 68, 172 };
double i = BitConverter.ToUInt32(m, 0) / 65536.0; // 44100.0
The conversion between your original storage format and this one is fairly straightforward. You could probably simply reverse the bytes, although I'm not entirely sure which decimal digit is more significant.
Depending on how you answer #JonSkeet comment above will depend on the fractional value of this. However, this solution works for the integer part
byte[] m = new byte[4] { 172, 68, 0, 0 };
byte[] fraction = m.Reverse().Take(2).ToArray();
byte[] integer = m.Reverse().Skip(2).Take(2).ToArray();
System.Diagnostics.Debug.Print("{0}", BitConverter.ToUInt16(integer, 0));
Related
First, I had read many posts and tried BitConverter methods for the conversion, but I haven't got the desired result.
From a 2 byte array of:
byte[] dateArray = new byte[] { 0x07 , 0xE4 };
Y need to get an integer with value 2020. So, the decimal of 0x7E4.
Following method does not returning the desired value,
int i1 = BitConverter.ToInt16(dateArray, 0);
The endianess tells you how numbers are stored on your computer. There are two possibilities: Little endian and big endian.
Big endian means the biggest byte is stored first, i.e. 2020 would become 0x07, 0xE4.
Little endian means the lowest byte is stored first, i.e. 2020 would become 0xE4, 0x07.
Most computers are little endian, hence the other way round a human would expect. With BitConverter.IsLittleEndian, you can check which type of endianess your computer has. Your code would become:
byte[] dateArray = new byte[] { 0x07 , 0xE4 };
if(BitConverter.IsLittleEndian)
{
Array.Reverse(dataArray);
}
int i1 = BitConverter.ToInt16(dateArray, 0);
dateArray[0] << 8 | dateArray[1]
Please help me to understand the different between Convert and BitConverter. In the below example, the above two methods give me two different answer:
UInt64 x = 0x4028b0a3d70a3d71;
// Use Convert
double d = Convert.ToDouble(x); // d = 4.6231392352297441E+18
// Use BitConverter
byte[] xArray = BitConverter.GetBytes(x);
double d1 = BitConverter.ToDouble(xArray, 0); // d1 = 12.345
Thank you
These two methods are used for different purposes; Convert.ToDouble(x) is equivalent to a cast: (double)x; which can be useful if you need the integer value to be treated as a floating point value, say, for mathematical operations:
int x = 7;
Console.WriteLine(x / 3); // 2
Console.WriteLine(Convert.ToDouble(x) / 3); // 2.3333333333333335
Console.WriteLine((double)x / 3); // 2.3333333333333335
BitConverter class is useful if you want to transmit the value over the network as a series of bytes; you'd use the BitConverter.GetBytes() on the sending side, and BitConverter.ToOriginalType() on the receiving end:
double x = 12.345;
byte[] xArray = BitConverter.GetBytes(x);
// Send xArray to another system over the network
// ...on the receiving system, presuming same endianness:
double d1 = BitConverter.ToDouble(xArray, 0); // d1 = 12.345
Now, in your example, let's take a look at what happens to the value of x in both cases:
UInt64 x = 0x4028b0a3d70a3d71;
// Use Convert
double d = Convert.ToDouble(x); // d = 4.6231392352297441E+18
d is a cast of x to double; in decimal form, 0x4028b0a3d70a3d71 = 4,623,139,235,229,744,497 = 4.623139235229744497+18 in scientific notation. No magic here, it's pretty much what you'd expect to happen. Onward.
// Use BitConverter
byte[] xArray = BitConverter.GetBytes(x);
double d1 = BitConverter.ToDouble(xArray, 0); // d1 = 12.345
...what? well, let's see how the double type is stored in memory. According to IEEE 754 specification for double, the format is:
first bit is a sign bit (0 = positive; 1 = negative)
next 11 bits are the exponent
next 52 bits are the significand (well, 53, but only 52 are stored)
Here's the binary representation of 0x4028b0a3d70a3d71, arranged into the 3 sections we need to consider:
0 10000000010 1000101100001010001111010111000010100011110101110001
The following formula is used to convert this storage format to an actual numeric value:
(-1)sign x (1.b51b50...b0)base2 x 2exponent - 1023
Instead of going through this math manually, we can use this awesome floating point converter; here's the snapshot of the result:
See the decimal result? 12.345, same as what you're getting with BitConverter.ToDouble(xArray, 0) - but certainly not the same as the casting operation performed by Convert.ToDouble(x)
The first:
you convert int hex representation to double
The second:
you treat the value in x as a bit representation of a double, not integer.
I've got this code
BitConverter.GetBytes(width).CopyTo(resultBytes, 0);
If the width is 12 it returns one byte not 4, is there a built in function to resize the array leaving 0's at the beginning
to output [0, 0, 0, 12] instead of [12].
What is the type of width? Bit converter just converts the type to an array of appropriate size. If you say
long x = 1 ;
int y = 2 ;
short z = 3 ;
byte[] x_bytes = BitConverter.GetBytes(x) ;
byte[] y_bytes = BitConverter.GetBytes(y) ;
byte[] z_bytes = BitConverter.GetBytes(z) ;
You'll get back 8-, 4- and 2-byte arrays, respectively. You can cast to the desired type:
byte[] bytes = BitConverter.GetBytes( (int) x ) ;
And if you say something like
byte[] bytes = BitConverter.GetBytes(1) ;
You'll get back an array of 4 bytes: the type of an unsuffixed integer literal is the smallest type in which will fit, in order of preference: int, uint, long, ulong. If the literal is suffixed, it will be the type specified by the suffix (e.g., 1L will give you an 8-byte long).
If you are converting an expression, such as:
byte[] bytes = BitConverter.GetBytes( ((3*x + 2&y + z) << 3 ) & 5L ) ;
What gets converted is, of course, the type produced by evaluating the expression.
you need to cast width to int in order to get 4 bytes, because the result of GetBytes() is dependent on the type passed in:
BitConverter.GetBytes((int)width).CopyTo(resultBytes, 0);
Maybe it's the simplest solution ever, but what about Array.Reverse:
BitConverter.GetBytes(4).CopyTo(resultBytes, 0); // [4, 0, 0, 0]
Array.Reverse(resultBytes); // [0, 0, 0, 4]
I am using BitConverter.ToInt32 to convert a Byte array into int.
I have only two bytes [0][26], but the function needs 4 bytes, so I have to add two 0 bytes to the front of the existing bytes.
What is the quickest method.
Thank you.
You should probably do (int)BitConverter.ToInt16(..) instead. ToInt16 is made to read two bytes into a short. Then you simply convert that to an int with the cast.
You should call `BitConverter.ToInt16, which only reads two bytes.
short is implicitly convertible to int.
Array.Copy. Here is some code:
byte[] arr = new byte[] { 0x12, 0x34 };
byte[] done = new byte[4];
Array.Copy(arr, 0, done, 2, 2); // http://msdn.microsoft.com/en-us/library/z50k9bft.aspx
int myInt = BitConverter.ToInt32(done); // 0x00000026
However, a call to `BitConverter.ToInt16(byte[]) seems like a better idea, then just save it to an int:
int myInt = BitConverter.ToInt16(...);
Keep in mind endianess however. On little endian machines, { 0x00 0x02 } is actually 512, not 2 (0x0002 is still 2, regardless of endianness).
Which is the fastest way to convert a byte[] to float[] and vice versa (without a loop of course).
I'm using BlockCopy now, but then I need the double memory. I would like some kind of cast.
I need to do this conversion just to send the data through a socket and reconstruct the array in the other end.
Surely msarchet's proposal makes copies too. You are talking about just changing the way .NET thinks about a memory area, if you dont' want to copy.
But, I don't think what you want is possible, as bytes and floats are represented totally different in memory. A byte uses exactly a byte in memory, but a float uses 4 bytes (32 bits).
If you don't have the memory requirements to store your data, just represent the data as the data type you will be using the most in memory, and convert the values you actually use, when you use them.
How do you want to convert a float (which can represent a value between ±1.5 × 10−45 and±3.4 × 10^38) into a byte (which can represent a value between 0 and 255) anyway?
(see more info her about:
byte: http://msdn.microsoft.com/en-us/library/5bdb6693(v=VS.100).aspx
float: http://msdn.microsoft.com/en-us/library/b1e65aza.aspx
More about floating types in .NET here: http://csharpindepth.com/Articles/General/FloatingPoint.aspx
You can use StructLayout to achieve this (from Stack Overflow question C# unsafe value type array to byte array conversions):
[StructLayout(LayoutKind.Explicit)]
struct UnionArray
{
[FieldOffset(0)]
public Byte[] Bytes;
[FieldOffset(0)]
public float[] Floats;
}
static void Main(string[] args)
{
// From bytes to floats - works
byte[] bytes = { 0, 1, 2, 4, 8, 16, 32, 64 };
UnionArray arry = new UnionArray { Bytes = bytes };
for (int i = 0; i < arry.Bytes.Length / 4; i++)
Console.WriteLine(arry.Floats[i]);
}
IEnumerable<float> ToFloats(byte[] bytes)
{
for(int i = 0; i < bytes.Length; i+=4)
yield return BitConverter.ToSingle(bytes, i);
}
Two ways if you have access to LINQ:
var floatarray = ByteArry.AsEnumerable.Cast<float>().ToArray();
or just using Array Functions
var floatarray = Array.ConvertAll(ByteArray, item => (float)item);