Home > OS >  Is there a nicer way to Cast the result of Enumerable.Range to type Double?
Is there a nicer way to Cast the result of Enumerable.Range to type Double?

Time:09-23

To make an array of doubles starting from 1 to 10 I currently am doing:

Dim N() As Double = Enumerable.Range(1, 10).Select(Function(x) CDbl(x)).ToArray

My technique seems inefficient and indirect. I see that ToArray has the space for arguments but whenever I try ToArray(Double) or ToArray(Of Double) it gives me an error.

What is the correct way to cast the elements to type Double when creating an array through Enumerable.Range?

CodePudding user response:

If you have a finite length and know the numbers in advance, the most efficient way would be to create the array with the upper-bounds and set the items individually. The compiler doesn't need to infer the upper-bounds when you explicitly specify it:

Dim n(9) As Double
n(0) = 1
n(1) = 2
'etc...

' or even more concise
For counter As Integer = 1 To 0
    n(counter - 1) = counter
Next

An alternative would be to create the array with an explicit initialization. This is "less performant" in that the compiler has to infer the upper-bounds, though I would imagine it is a marginal performance hit:

Dim n() As Double = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }

If you do not want to type the values out, then you can do what you're doing and create a range and then cast the result. An alternative to using Select would be to use the ConvertAll method:

Dim n() As Double = Array.ConvertAll(Enumerable.Range(1, 10).ToArray(), Function(counter) Convert.ToDouble(counter))

Long story short, what you're doing isn't wrong. If you are pinching for performance, it is not the most optimal solution, but more often than not you should be just fine.

CodePudding user response:

Is there a nicer way to ...

Well, nicer is relative - but to which quality? If performance is that quality, then avoid LINQ. If simplicity is that quality, then use LINQ.

Dim count = 1000000

Dim sw As New Stopwatch()

sw.Start()
Dim n = Enumerable.Range(1, count).Select(Function(x) CDbl(x)).ToArray()
sw.Stop() 
Console.WriteLine(sw.ElapsedMilliseconds)

sw.Restart()
Dim m(count - 1) As Double
For i = 0 To m.GetUpperBound(0)
    m(i) = CDbl(i   1)
Next
sw.Stop() 
Console.WriteLine(sw.ElapsedMilliseconds)

35
6

Clearly, one is cleaner, and the other faster. Which is nicer is up to you...

  • Related