I can't seem to figure out a way to convert an sbyte back to original integer value.
int k = 148;
sbyte t = (sbyte)k;
int asd = Convert.ToInt32(t);
The value of asd is -108. How can I convert the sbyte back to int to get the original value of 148?
Thanks
Assuming you want the result to be in the range 0-255 inclusive, the simplest approach is:
int asd = t & 0xff;
This will promote k to an int, then take just the bottom 8 bits, leaving all the top 24 bits as 0.
However, I'd question why you'd want to use sbyte for this in the first place. It's very very rarely a good idea - one of the design flaws of Java (in my view) was to make byte a signed type. If you want to represent byte values, byte would be more appropriate.
As sbyte is in range -128 to 127, ideally your existing method should not return sbyte when the return value can be between 0-255.
But anyway, you can first try converting sbyte into byte and then into int.
I suppose following code should work
int k = 148;
sbyte t = (sbyte)k;
byte b=(byte)t;
Console.WriteLine(b);
Console.WriteLine();
int asd = Convert.ToInt32(b);
Console.WriteLine(asd);
An sbyte holds values from -128 to 127 because the first bit represents plus or minus.
Cast your sbyte to byte first, then convert to int.
int k = 148;
sbyte t = (sbyte)k;
int asd = (int)(byte)k;
Assert.AreEqual(148, asd);
Related
I'm looking for a good and efficient way to store integers in bytes.
The situation is the following:
I have two integers, Value 1 is "1857" (11bit) and Value 2 is "14" (4bit) and 2 bytes (16bit).
What I'm looking for, is to store the 2 integers in the 2 bytes. This mean cut the first integer, put 8 bits in the first byte and the rest plus the second integer in the second byte. Also I need to get them back together.
Is there a way or .net class to do that?
I've found the BitConverter class, but thats not what I'm looking for because this class only convert one integer to an full byte array.
You could use bit operators for that: bitwise and (&), or (|), and shift left (<<) and right (>>):
int value1 = 1857;
int value2 = 14;
int result = value1 | (value2 << 11);
To get the original values back you have to reverse that:
int result1 = result & 0x7ff; // 1857
int result2 = result >> 11; // 14
I have a number
int number = 509; // integer
string bool_number = Convert.ToString(number, 2); // same integer converted to binary no
I want to bitwise or this number with hex values 0x01, 0x02, 0x04 and 0x08.
(e.g. something like this)
result = number | 0x01
How can I do it? Should I convert number to hex form or whats the right way?
You can use hexadecimal values as numeric literals...
int number = 509;
int hexNumber = 0x02;
int newNumber = number | hexNumber;
// whatever
string newNumberAsBinaryString = Convert.ToString(newNumber, 2);
Console.WriteLine(newNumber);
// etc.
If you need to input a hex string and convert it to a numeric type:
int num = Int32.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
If you need to output a numeric type as hex:
Console.WriteLine(num.ToString("x"));
// or
Console.WriteLine("{0:x}", num);
See also MSDN's page on dealing with hex strings.
An int value isn't in any particular base. You can use bitwise operators on an int at any time - there's no need to convert it first. For example:
int a = 509;
int b = 0x1fd;
The variables a and b have exactly the same value here. I happen to have used a decimal literal to initialize a, and a hex literal to initialize b, but the effect is precisely the same.
So you can bitwise OR your ints at any time. Your example (adding a suitable declaration and semicolon to make it compile):
int result = number | 0x01;
will work just fine - you don't need to do anything to prepare number for this sort of usage. (Incidentally, this will do nothing, because the result of a bitwise OR of the numbers 509 and 1 is 509. If you write 509 in binary you get 111111101 - the bottom bit is already 1, so ORing in 1 won't change anything.)
You should avoid thinking in terms of things like "hex values", because there isn't really any such thing in C#. Numeric bases are only relevant for numbers represented as strings, which typically means either literals in source code, or conversions done at runtime. For example, if your program accepts a number as a command line argument, then that will arrive as a string, so you'll need to know its base to convert it correctly to an int. But once it's an int it's just an int - there's no such thing as a hex value or a decimal value for an int.
From a library I'm working with I recieve an array of ushort.
I want to convert them in an array of float: The first ushort represents the 16 MSB of the first float and the second ushort is the 16 LSB of the first float, and so on.
I tried with something like the following, but the value is cast as the value of the integer, not the raw bits:
ushort[] buffer = { 0xBF80, 0x0000 };
float f = (uint)buffer[0] << 16 | buffer[1];
// expected result => f == -1 (0xBF800000)
// effective result => f == 3.21283686E+9 (0x4F3F8000)
Any suggestion?
Have a look at the System.BitConverter class.
In particular, the ToSingle method which takes a sequence of bytes and converts them to a float.
ushort[] buffer = {0xBF80, 0x0000};
byte[] bytes = new byte[4];
bytes[0] = (byte)(buffer[1] & 0xFF);
bytes[1] = (byte)(buffer[1] >> 8);
bytes[2] = (byte)(buffer[0] & 0xFF);
bytes[3] = (byte)(buffer[0] >> 8);
float value = BitConverter.ToSingle( bytes, 0 );
EDIT
In the example, I had reversed the MSB/LSB order.. Now it is correct
You should use the BitConverter class for that.
Convert the two ushorts to byte arrays with BitConverter.GetBytes(UInt16), concatenate the two arrays and use BitConverter.ToSingle(byte[] value,int startIndex) to convert the 4 bytes in the resulting array to a float.
I'd look at the System.BitConverter class. You can use BitConverter.GetBytes to turn your ushorts into byte arrays, then combine your byte arrays and use BitConverter to turn the byte array into a float.
Use a C# union:
[System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)]
public struct FloatUShortUnion {
[System.Runtime.InteropServices.FieldOffset(0)]
float floatValue;
[System.Runtime.InteropServices.FieldOffset(0)]
ushort short1;
[System.Runtime.InteropServices.FieldOffset(16)]
ushort short2;
}
You will need to use System.BitConverter, and convert the shorts to bytes.
http://msdn.microsoft.com/en-us/library/system.bitconverter.tosingle.aspx
I know this threads super old but I had a similar problem nothing above fixed. I had to send a decimal value to a plc using modbus and my only option to write to the registers was a ushort array. Luckily the software on the plc could convert the ushort array back to the decimal, the issue was reading the data from the plc. Here is what I was able to get to work. ConvertTo takes the users input and creates the ushort array for the write and ConvertFrom takes the ushort array the program receives from the plc and converts it back to the float.
private ushort[] ConvertTo(string value)
{
var bytes = BitConverter.GetBytes(float.Parse(value));
return new ushort[] {
BitConverter.ToUInt16(bytes, 0),
BitConverter.ToUInt16(bytes, 2)
};
}
private float ConvertFrom(ushort valueOne, ushort valueTwo)
{
byte[][] final = Array.ConvertAll(new ushort[] { valueOne, valueTwo }, delegate (ushort item) { return BitConverter.GetBytes(item); });
return BitConverter.ToSingle(new byte[4] { final[0][0], final[0][1], final[1][0], final[1][1] }, 0);
}
I need to take an int and turn it into its byte form.
i.e. I need to take '1' and turn it into '00000001'
or '160' and turn it into '10100000'
Currently, I am using this
int x = 3;
string s = Convert.ToString(x, 2);
int b = int.Parse(s);
This is an awful way to do things, so I am looking for a better way.
Any Suggestions?
EDIT
Basically, I need to get a list of every number up to 256 in base-2. I'm going to store all the numbers in a list, and keep them in a table on my db.
UPDATE
I decided to keep the base-2 number as a string instead of parsing it back. Thanks for the help and sorry for the confusion!
If you need the byte form you should take a look at the BitConverter.GetBytes() method. It does not return a string, but an array of bytes.
The int is already a binary number. What exactly are you looking to do with the new integer? What you are doing is setting a base 10 number to a base 2 value. That's kind of confusing and I think you must be trying to do something that should happen a different way.
I don't know what you need at the end ... this may help:
Turn the int into an int array:
byte[] bytes = BitConverter.GetBytes(x);
Turn the int into a bit array:
BitArray bitArray = new BitArray(new[] {x});
You can use BitArray.
The code looks a bit clumsy, but that could be improved a bit.
int testValue = 160;
System.Collections.BitArray bitarray = new System.Collections.BitArray(new int[] { testValue });
var bitList = new List<bool>();
foreach (bool bit in bitarray)
bitList.Add(bit);
bitList.Reverse();
var base2 = 0;
foreach (bool bit in bitList)
{
base2 *= 10; // Shift one step left
if (bit)
base2++; // Add 1 last
}
Console.WriteLine(base2);
I think you are confusing the data type Integer with its textual representation.
int x = 3;
is the number three regardless of the representation (binary, decimal, hexadecimal, etc.)
When you parse the binary textual representation of an integer back to integer you are getting a different number. The framework assumes you are parsing the number represented in the decimal base and gives the corresponding integer.
You can try
int x = 1600;
string s = Convert.ToString(x, 2);
int b = int.Parse(s);
and it will throw an exception because the binary representation of 1600 interpreted as decimal
is too big to fit in an integer
I have this code for converting a byte[] to float[].
public float[] ConvertByteToFloat(byte[] array)
{
float[] floatArr = new float[array.Length / sizeof(float)];
int index = 0;
for (int i = 0; i < floatArr.Length; i++)
{
floatArr[i] = BitConverter.ToSingle(array, index);
index += sizeof(float);
}
return floatArr;
}
Problem is, I usually get a NaN result! Why should this be? I checked if there is data in the byte[] and the data seems to be fine. If it helps, an example of the values are:
new byte[] {
231,
255,
235,
255,
}
But this returns NaN (Not a Number) after conversion to float. What could be the problem? Are there other better ways of converting byte[] to float[]? I am sure that the values read into the buffer are correct since I compared it with my other program (which performs amplification for a .wav file).
If endianness is the problem, you should check the value of BitConverter.IsLittleEndian to determine if the bytes have to be reversed:
public static float[] ConvertByteToFloat(byte[] array) {
float[] floatArr = new float[array.Length / 4];
for (int i = 0; i < floatArr.Length; i++) {
if (BitConverter.IsLittleEndian) {
Array.Reverse(array, i * 4, 4);
}
floatArr[i] = BitConverter.ToSingle(array, i * 4);
}
return floatArr;
}
Isn't the problem that the 255 in the exponent represents NaN (see Wikipedia in the exponent section), so you should get a NaN. Try changing the last 255 to something else...
If it's the endianness that is wrong (you are reading big endian numbers) try these (be aware that they are "unsafe" so you have to check the unsafe flag in your project properties)
public static unsafe int ToInt32(byte[] value, int startIndex)
{
fixed (byte* numRef = &value[startIndex])
{
var num = (uint)((numRef[0] << 0x18) | (numRef[1] << 0x10) | (numRef[2] << 0x8) | numRef[3]);
return (int)num;
}
}
public static unsafe float ToSingle(byte[] value, int startIndex)
{
int val = ToInt32(value, startIndex);
return *(float*)&val;
}
I assume that your byte[] doesn't contain the binary representation of floats, but either a sequence of Int8s or Int16s. The examples you posted don't look like audio samples based on float (neither NaN nor -2.41E+24 are in the range -1 to 1. While some new audio formats might support floats outside that range, traditionally audio data consists of signed 8 or 16 bit integer samples.
Another thing you need to be aware of is that often the different channels are interleaved. For example it could contain the first sample for the left, then for the right channel, and then the second sample for both... So you need to separate the channels while parsing.
It's also possible, but uncommon that the samples are unsigned. In which case you need to remove the offset from the conversion functions.
So you first need to parse current position in the byte array into an Int8/16. And then convert that integer to a float in the range -1 to 1.
If the format is little endian you can use BitConverter. Another possibility that works with both endiannesses is getting two bytes manually and combining them with a bit-shift. I don't remember if little or big endian is common. So you need to try that yourself.
This can be done with functions like the following(I didn't test them):
float Int8ToFloat(Int8 i)
{
return ((i-Int8.MinValue)*(1f/0xFF))-0.5f;
}
float Int16ToFloat(Int16 i)
{
return ((i-Int16.MinValue)*(1f/0xFFFF))-0.5f;
}
Depends on how you want to convert the bytes to float. Start out by trying to pin-point what is actually stored in the byte array. Perhaps there is a file format specification? Other transformations in your code?
In the case each byte should be converted to a float between 0 and 255:
public float[] ConvertByteToFloat(byte[] array)
{
return array.Select(b => (float)b).ToArray();
}
If the bytes array contains binary representation of floats, there are several representation and if the representation stored in your file does not match the c# language standard floating point representation (IEEE 754) weird things like this will happen.