i want to convert double array to byte array and byte array to double array
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Linq;
namespace BitConversion
{
class Program
{
static void Main(string[] args)
{
double[] Array = new double[] { 10.0, 20.0, 30.0, 40.0 };
byte[] byteArray = GetBytesAlt(Array);
for (int i = 0; i < byteArray.Length; i++)
{
Console.Write(byteArray[i]);
Console.Write(",");
}
Console.WriteLine();
double[] doubleArray = GetDoublesAlt(byteArray);
for (int i = 0; i < doubleArray.Length; i++)
{
Console.Write(doubleArray[i]);
Console.Write(",");
}
Console.WriteLine();
Console.ReadLine();
}
/// <summary>
/// convert to bytes
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
static byte[] GetBytesAlt(double[] values)
{
/*var result = new byte[values.Length * sizeof(double)];
Buffer.BlockCopy(values, 0, result, 0, result.Length);
return result;*/
return values.SelectMany(value => BitConverter.GetBytes(value)).ToArray();
//return values.SelectMany(value => BitConverter.GetBytes(value)).ToArray();
}
static double[] GetDoublesAlt(byte[] bytes)
{
/* var result = new double[bytes.Length / sizeof(double)];
Buffer.BlockCopy(bytes, 0, result, 0, bytes.Length);
return result;*/
return Enumerable.Range(0, bytes.Length / sizeof(double)).Select(offset => BitConverter.ToDouble(bytes, offset * sizeof(double))).ToArray();
}
}
}
with the convert approach the when bytes are converted back to the doubles
the numbers are getting as 10.0,20.0, 30.0, 40.0.....
How to get back the same numbers?
I mean if the double entered is 10.0, 20.0 , 30.0 , 40.0
and i have get back the same number is 10.0,20.0,30.0,40.0.
There is no issue with your program - if you slightly modify your program and print the original as well as round-tripped array, you will indeed see that you get the same out-put.
For example,
Original: 10.1,20.2,30,40,
Round-trip: 10.1,20.2,30,40,
Here's the slightly modified code
class Program
{
static void Main(string[] args)
{
double[] Array = new double[] { 10.1, 20.2, 30.0, 40.0 };
Console.Write("Original:\t");
PrintArray(Array);
byte[] byteArray = GetBytesAlt(Array);
double[] doubleArray = GetDoublesAlt(byteArray);
Console.Write("Round-trip:\t");
PrintArray(doubleArray);
Console.ReadLine();
}
static void PrintArray(Double[] array)
{
for (int i = 0; i < array.Length; i++)
{
Console.Write(array[i]);
Console.Write(",");
}
Console.WriteLine();
}
// rest of methods are same
...
}
You are getting the correct numbers, it is only in writing to the console that you are loosing your .0 the two numbers are equivalant. 10.0 and 10. This is what your doubleArray looks like before writing.
Try changing your Console.Write statement to this:
for (int i = 0; i < doubleArray.Length; i++)
{
//Since you are forcing the .0 you need to make sure you have enough #'s
//for the level of precision you need. It is actually better to use the
//system default since 10.0 and 10 are functionaly equivalent.
Console.Write( doubleArray[i].ToString("##.0####"));
Console.Write(",");
}
Related
i use Modbus/TCP to get data, data type is LReal.
but i want LReal to int.
this is my data.
staic_13 data is 「4.232」
but i get [80] 16400 [81]-2098 [82] -9962 [83] -30933.
i don't know how turn to double
Based on this experimental Python code,
>>> x = [16400, -2098, -9962, -30933]
>>> struct.unpack(">d", struct.pack(">4h", *x))
(4.242,)
it looks like you'd need to concatenate those 4 16-byte integers in big-endian format, then interpret those 8 bytes as a single big-endian double.
In .NET 6 (see this fiddle):
using System.Buffers.Binary;
using System;
short[] values = {16400, -2098, -9962, -30933};
byte[] buf = new byte[values.Length * sizeof(short)];
for (int i = 0; i < values.Length; i++)
{
BinaryPrimitives.WriteInt16BigEndian(buf.AsSpan(i * sizeof(short)), values[i]);
}
double result = BinaryPrimitives.ReadDoubleBigEndian(buf);
Console.WriteLine(result);
In .NET 4 (see this fiddle):
using System;
public class Program
{
public static void Main()
{
short[] values = {16400, -2098, -9962, -30933};
byte[] buf = new byte[8];
for (int i = 0; i < 4; i++)
{
byte[] sh_buf = BitConverter.GetBytes(values[i]);
if(BitConverter.IsLittleEndian) {
// Flip the bytes around if we're little-endian
buf[(3 - i) * 2] = sh_buf[0];
buf[(3 - i) * 2 + 1] = sh_buf[1];
} else {
buf[i * 2] = sh_buf[0];
buf[i * 2 + 1] = sh_buf[1];
}
}
double result = BitConverter.ToDouble(buf, 0);
Console.WriteLine(result);
}
}
I have some code that wasn't written by myself and I'm trying to use it to build a Poker ICM calculator program. This program takes an array of stack sizes and prize payouts and calculates each players prize equity.
The code works for 3 prizes but when I add a 4th prize I get an index out of bounds error because I'm trying to get permutation[3] when the object only contains indexes 0 to 2. The problem is I can't understand how the size of permuation gets set so I can't figure out how to adjust the code to work for higher numbers of prizes. I'd appreciate some help.
Below is a minimum working example with working and non-working code in the main method and a comment to indicate where the error occurs.
ICMCalculator.cs
class ICMCalculator
{
public double[] CalcEV(int[] structure, int[] chips)
{
//the probability of a players position
double[,] probabilitys = new double[structure.Length, chips.Length];
//the expected value of the player
double[] EVs = new double[chips.Length];
int[] players = new int[chips.Length];
for (int i = 0; i < players.Length; ++i)
players[i] = i;
IEnumerable<int[]> permutations;
for (int i = 0; i < structure.Length; ++i)
{
permutations = (new Permutation()).Enumerate(players, i + 2);
foreach (int[] permutation in permutations)
{
// OUT OF BOUNDS ERROR OCCURS HERE
probabilitys[i, permutation[i]] += CalcPermutationProbability(permutation, chips);
}
}
for (int i = 0; i < structure.Length; ++i)
{
for (int j = 0; j < chips.Length; ++j)
EVs[j] += probabilitys[i, j] * structure[i];
}
return EVs;
}
private double CalcPermutationProbability(int[] permutations, int[] chips)
{
double probability = 1.0F;
int chips_sum = chips.Sum();
for (int i = 0; i < permutations.Length; ++i)
{
probability *= System.Convert.ToDouble(chips[permutations[i]]) / System.Convert.ToDouble(chips_sum);
chips_sum -= chips[permutations[i]];
}
return probability;
}
}
Permutation.cs
class Permutation
{
public IEnumerable<T[]> Enumerate<T>(IEnumerable<T> nums, int length)
{
var perms = _GetPermutations<T>(new List<T>(), nums.ToList(), length);
return perms;
}
private IEnumerable<T[]> _GetPermutations<T>(IEnumerable<T> perm, IEnumerable<T> nums, int length)
{
if (length - perm.Count() <= 0)
{
yield return perm.ToArray();
}
else
{
foreach (var n in nums)
{
var result = _GetPermutations<T>(perm.Concat(new T[] { n }),
nums.Where(x => x.Equals(n) == false), length - perm.Count());
foreach (var xs in result)
yield return xs.ToArray();
}
}
}
}
Utils.cs
class Utils
{
public static string DoubleArrayToString(double[] doubles)
{
StringBuilder sb = new StringBuilder();
foreach (double dub in doubles)
{
sb.AppendLine(Utils.Format2DP(dub));
}
return sb.ToString().Trim();
}
}
Program.cs
static class Program
{
static void Main()
{
// THIS WORKS
ICMCalculator ev = new ICMCalculator();
int[] stacks = new int[] { 4500, 2700, 1800, 1000, 500 };
int[] prizes = new int[] { 84,36,18 };
int prizePool = prizes.Sum();
double[] equity = ev.CalcEV(prizes, stacks);
Console.WriteLine(Utils.DoubleArrayToString(equity));
// THIS THROWS INDEX ERROR
ev = new ICMCalculator();
stacks = new int[] { 4500, 2700, 1800, 1000, 500 };
prizes = new int[] { 84,36,18,9 };
prizePool = prizes.Sum();
equity = ev.CalcEV(prizes, stacks);
Console.WriteLine(Utils.DoubleArrayToString(equity));
}
}
To be clear, I believe that each 'permutation' should be the length of structure.Length. I don't want to avoid the out of bounds error by reducing the max value of i. I think I need to increase the size of each permuation to match structure.Length but I'm unable to figure out how to do this.
If resolved correctly, the code that currently fails should output the values: 50.82, 37.85, 29.16, 19.01, 10.15
I think the problem is in this line:
var result = _GetPermutations<T>(perm.Concat(new T[] { n }),
nums.Where(x => x.Equals(n) == false), length - perm.Count());
Instead, I think it should be
var result = _GetPermutations<T>(perm.Concat(new T[] { n }),
nums.Where(x => x.Equals(n) == false), length);
The problem here is that we are double-counting the length of the permutation found so far when we determine whether to stop further recursion.
The condition length - perm.Count() <= 0 (which can be simplified to perm.Count() >= length) is used to stop further calls to _GetPermutations if the permutation perm generated so far is long enough to be returned. This relies on the parameter length being the required length of the resulting permutations. However, by passing length - perm.Count() in the recursive call to _GetPermutations(), then we are reducing the value of length that inner calls to _GetPermutations() receive, causing them to stop the recursion early with permutations that are too short.
I am stuck at typical problem of conversion of data formats in WPF application in C#. I am new to C#. The GUI i am working on is displaying temperatures after getting the bytes data from the UDS messages.
When the data received in the format like 41c00000( which is in float format), the below function is able to convert the data into temperature in Celsius (both negative and positive).
public static float ComposeFloat(List<string> list, bool bigEndian)
{
float val;
byte[] payload = { 0, 0, 0, 0 }; // Used for float conversions
// BitConverter needs a little endian list
if (bigEndian)
{
list.Reverse();
}
for (int i = 0; i < 4; i++)
{
payload[i] = Convert.ToByte(list[i], 16);
}
val = BitConverter.ToSingle(payload, 0); // convert to an ieee754 float
return val;
}
But for some other temperature sensor in our system, the UDS is giving the data in the format 00000028. Since the UDS message was giving the temperature in integer format, I modified the above code as shown below, completely ignoring the case about what will happen if the temperature would be negative, which is really big mistake.
public static float ComposeFloat_FromInt(List<string> list, bool bigEndian)
{
float val;
int[] payload = { 0, 0, 0, 0 };
if (bigEndian)
{
list.Reverse();
}
for (int i = 0; i < 4; i++)
{
payload[i] = Convert.ToInt32(list[i], 16);
}
val = (float)payload[0];
return val;
}
Please guide me what will be the data received from the system when temperature is negative by giving some example and how should i modify the function to cover the negative temperature case.
Assuming the system sends temperatures as 32-bit signed integers using two's complement, you can use BitConverter.ToInt32 method to convert the array directly to a signed integer:
public static int ComposeFloat_FromInt(List<string> list, bool bigEndian)
{
int val;
byte[] payload = { 0, 0, 0, 0 };
if (bigEndian)
{
list.Reverse();
}
for (int i = 0; i < 4; i++)
{
payload[i] = Convert.ToByte(list[i], 16);
}
val = BitConverter.ToInt32(payload, 0); // Converts a byte array to Int32
return val;
}
Sample string:
A3148579
Expected result:
798514A3
I tried this code:
public static string Reverse(string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
the actual result is 9758413A
but I want 798514A3
thanks everyone
You can try below code. This is just to give you a idea and you can update based on the test cases and requirement. Below code works fine for your input which you have mentioned. I have not considered if the length is odd. You can do your research and update logic which will help you to learn and know more.
string input = "A3148579";
Stack stack = new Stack();
int count = 0;
string output = "";
for (int i = 0; i < input.Length/2; i++)
{
stack.Push(input.Substring(count, 2));
count = count + 2;
}
while (stack.Count > 0)
{
output += stack.Pop().ToString();
}
You can split the initial string into chunks of size = 2 (e.g. with a help of Substring); note that ToCharArray() returns chars i.e. chunks of size = 1.
Let's generalize the solution: now we have size of chunks
Code:
using System.Linq;
...
public static string Reverse(string s, int size = 2) {
if (size < 1)
throw new ArgumentOutOfRangeException(nameof(size));
if (string.IsNullOrEmpty(s))
return s;
int n = s.Length / size + (s.Length % size == 0 ? 0 : 1);
return string.Concat(Enumerable
.Range(0, n)
.Select(i => i < n - 1 ? s.Substring(i * size, size) : s.Substring(i * size))
.Reverse());
}
Demo:
Console.Write(Reverse("A3148579"));
Outcome:
798514A3
C# Example: Split An Array into Multiple Smaller Arrays
Use Lambda expression to extends Array class to include a new method called Split:
public static class MyArrayExtensions
{
/// <summary>
/// Splits an array into several smaller arrays.
/// </summary>
/// <typeparam name="T">The type of the array.</typeparam>
/// <param name="array">The array to split.</param>
/// <param name="size">The size of the smaller arrays.</param>
/// <returns>An array containing smaller arrays.</returns>
public static IEnumerable<IEnumerable<T>> Split<T>(this T[] array, int size)
{
for (var i = 0; i < (float)array.Length / size; i++)
{
yield return array.Skip(i * size).Take(size);
}
}
}
Test the new array class method:
[TestMethod]
public void TestSplit2()
{
string str = "A3148579";
char[] array1 = new char[str.Length];
for (int i = 0; i < array1.Length; i++)
{
array1[i] = i;
}
// Split into smaller arrays of maximal 2 elements
IEnumerable<IEnumerable<int>> splited = array1.Split<int>(2);
int j = 0;
foreach (IEnumerable<int> s in splited){
j++;
}
log.InfoFormat("Splitted in to {0} smaller arrays.", j);
}
Finally you just need to reverse the resulted array(smaller).
I am passed a byte array which is then converted to arrays of primitives using System.Buffer.BlockCopy. Essentially my code looks like this:
void Convert(byte[] b)
{
int[] i1 = new int[100]; // real arrays much larger
double[] d1 = new double[100];
int iPos=0, iSize;
iSize = i1.Length * sizeof(int);
System.Buffer.BlockCopy(b, iPos, i1, 0, iSize);
iPos += iSize;
iSize = d1.Length * sizeof(double);
System.Buffer.BlockCopy(b, iPos, d1, 0, iSize);
iPos += iSize;
//etc: lots of arrays
b=null;
}
This is quite performant, but it's memory usage is obviously 2x the size of my byte array until b is freed.
Is there any way to directly cast sections of the byte array to my primitive arrays? One that does not involve copying the data (therefore doesn't double the memory usage), and presumably is even faster?
You can use unsafe code (I don't if you are allowed to use it). But you can try something like this (no need to use extra arrays, just the array of bytes):
unsafe public void Convert(void* b)
{
int i;
double* asDouble = (double*)b;
double sum1 = 0.0;
for (i = 0; i < 100; i++, asDouble++)
sum1 += *asDouble;
int* asInt = (int*)asDouble;
int sum2 = 0;
for (i = 0; i < 100; i++, asInt++)
sum2 += *asInt;
}
public unsafe void SomeThing()
{
byte[] rawbytes = new byte[44000];
// Fill the "rawbytes" array somehow
fixed (byte* ptr = rawbytes)
{
Convert(ptr);
}
}
It is possible using unsafe code. One solution using a union (what my not be applicable in your situation)
namespace TestApplication
{
using System;
using System.Runtime.InteropServices;
internal static class Program
{
private static unsafe void Main()
{
var x = new ByteDoubleUnion();
x.bytes[0] = 24;
x.bytes[1] = 45;
x.bytes[2] = 68;
x.bytes[3] = 84;
x.bytes[4] = 251;
x.bytes[5] = 33;
x.bytes[6] = 9;
x.bytes[7] = 64;
// Prints pi.
Console.WriteLine(x.doubleValue);
Console.ReadLine();
}
}
[StructLayout(LayoutKind.Explicit)]
internal unsafe struct ByteDoubleUnion
{
[FieldOffset(0)]
internal Double doubleValue;
[FieldOffset(0)]
internal fixed Byte bytes[8];
}
}
and one solution just casting pointers.
namespace TestApplication
{
using System;
internal static class Program
{
private static unsafe void Main()
{
var bytes = new Byte[] { 24, 45, 68, 84, 251, 33, 9, 64 };
fixed (Byte* p = &bytes[0])
{
// Prints pi, too.
Console.WriteLine(*((Double*)p));
}
Console.ReadLine();
}
}
}
This is an attempt with unioned structure of arrays (unlike the array of struct in other postings) because this should be faster.
[StructLayout(LayoutKind.Explicit)]
public unsafe struct ByteBuffer
{
public const int IntSize=10;
public const int DoubleSize=5;
public const int IntBytes=sizeof(int)*IntSize;
public const int DoubleBytes=sizeof(double)*DoubleSize;
// Int array is unioned with byte array
[FieldOffset(0)]
fixed int int_array[IntSize];
[FieldOffset(0)]
fixed byte int_array_bytes[IntBytes];
// Double array us unioned with byte array
[FieldOffset(IntBytes)]
fixed double double_array[DoubleSize];
[FieldOffset(IntBytes)]
fixed byte double_array_bytes[DoubleBytes];
// Take array of bytes and distribute it
// by byte to each array
public ByteBuffer(byte[] b)
{
fixed(byte* ptr=int_array_bytes)
{
for(int i=0; i<IntBytes; i++)
{
ptr[i]=b[i];
}
}
fixed(byte* ptr=double_array_bytes)
{
for(int i=0; i<DoubleBytes; i++)
{
ptr[i]=b[IntBytes+i];
}
}
}
// Convert unmanaged array to managed array
public int[] ToIntArray()
{
int[] result=new int[IntSize];
fixed(int* ptr=int_array)
{
for(int i=0; i<IntSize; i++)
{
result[i]=ptr[i];
}
}
return result;
}
// Convert unmanaged array to managed array
public double[] ToDoubleArray()
{
double[] result=new double[DoubleSize];
fixed(double* ptr=double_array)
{
for(int i=0; i<DoubleSize; i++)
{
result[i]=ptr[i];
}
}
return result;
}
}
class Program
{
static void Main(string[] args)
{
// Load up with test data
byte[] data=new byte[..];
// I tested with 10 ints and 5 doubles encoded into bytes
//Now to test the Fast conversion
ByteBuffer bb=new ByteBuffer(data);
int[] data1=bb.ToIntArray();
double[] data2=bb.ToDoubleArray();
}
}