rex
rex

Reputation: 3183

Convert decimal[][] to double[][] in C#

I want to cast my 2D decimal arrays to double arrays. I would like this to be done rather efficiently but also be tidy. This looks nice and tidy. How can I extend it for 2D arrays?

Am I going to have to loop through the first dimension and apply the Linq/delegate style command or is there another way to do it with less code?

PS: I am not very concerned with losing precision past 3-4 decimal places.

Update: At the request of a comment, this is what I am proposing although want to avoid:

double[][] inputs = new double[inputsArray.Length][];
for (int i = 0; i < inputsArray.Length; i++)
{
    inputs[i] = Array.ConvertAll(inputsArray[i], x => (double)x);
}

Upvotes: 3

Views: 903

Answers (2)

D Stanley
D Stanley

Reputation: 152521

Unfortunately with a jagged array you'll have to convert each array separately, but it can still be done in a one-liner:

doubleArray = Array.ConvertAll(decimalArray, da => Array.ConvertAll(da, d => (double)d));

or using Linq:

doubleArray = decimalArray.Select(da => da.Select(d => (double)d).ToArray()).ToArray(); 

You'll have to try it to see which is faster; Array.ConvertAll may have some optimizations by combining the delegate and the Array creation.

BENCHMARKS

to address the debate of performance, I benchmarked the three proposed solutions:

  1. Array.Convert
  2. Linq
  3. Loops

Here are the code and the results

int I = 10000;
int J = 1000;

Random rand = new Random();

decimal[][] decimalArray = new decimal[I][];

decimalArray = Enumerable.Range(1,I).Select(i => 
     Enumerable.Range(1, J).Select (j => (decimal)rand.NextDouble()).ToArray()
   ).ToArray();


Stopwatch s = new Stopwatch();

// Array.ConvertAll
s.Start();
var doubleArray = Array.ConvertAll(decimalArray, da => Array.ConvertAll(da, d => (double)d));
s.Stop();
s.Dump();

// Linq    
s.Restart();
doubleArray = decimalArray.Select(da => da.Select(d => (double)d).ToArray()).ToArray(); 
s.Stop();
s.Dump();

// Loops
s.Restart();
doubleArray = new double[I][];
for(int i = 0; i < I; i++)
{
    decimal[] dda = decimalArray[i];
    doubleArray[i] = new double[dda.Length];
    double[] da = doubleArray[i];
    for(int j = 0; j < dda.Length; j++)
    {
        da[j] = (double)dda[j];
    }
}
s.Stop();
s.Dump();


Method          ElapsedMilliseconds 
-------------   ----------------------
Array.Convert   310 
Linq            478 
Loops           287   (7.5% faster that Array.Convert)

You can decide whether a 7.5% speed improvement is worth 7X the amount of code.

Upvotes: 5

digEmAll
digEmAll

Reputation: 57210

You can concatenate two Array.ConvertAll e.g. :

var dec2D = new decimal[100][];
var dbl2D = Array.ConvertAll(dec2D, x => Array.ConvertAll(x, y => (double)y));

Upvotes: 4

Related Questions