2012-05-23 16 views
6

Si quiero generar una matriz que va del 1 al 6 y aumenta en .01, ¿cuál es la forma más eficiente de hacerlo?C# Matriz de incrementos

Lo que yo quiero es una matriz, con minutos y MAXS sujetas a cambios después ... como esto: x[1,1.01,1.02,1.03...]

+0

¿Qué tal utilizar un bucle con un valor decimal? – Terminador

+6

Definir eficiente ... ¿menos código? ¿O más rápido? –

+0

¿Incrementar por .01 los valores dentro de la matriz? o incrementar el tamaño de la matriz en 1? – gsharp

Respuesta

14

Suponiendo una start, end y un valor increment, puede abstracta esta otra:

Enumerable 
    .Repeat(start, (int)((end - start)/increment) + 1) 
    .Select((tr, ti) => tr + (increment * ti)) 
    .ToList() 

Vamos a desglosarlo:

Enumerable.Repeat toma un número inicial, se repite para un número dado de elementos y devuelve un enumerable (Una colección). En este caso, empezamos con el elemento start, encontrar la diferencia entre start y end y se divide por el increment (esto nos da el número de incrementos entre start y end) y agregue para incluir el número original. Esto debería darnos la cantidad de elementos para usar. Solo ten en cuenta que dado que el increment es un decimal/doble, puede haber errores de redondeo cuando selecciones un int.

Select transforma todos los elementos de un enumerable dada una función de selector específico. En este caso, tomamos el número que se generó y el índice, y agregamos el número original con el índice multiplicado por el incremento.

Finalmente, la llamada al ToList guardará la colección en la memoria.

Si usted se encuentra el uso de esta frecuencia, entonces usted puede crear un método para hacer esto para usted:

public static List<decimal> RangeIncrement(decimal start, decimal end, decimal increment) 
{ 
    return Enumerable 
     .Repeat(start, (int)((end - start)/increment) + 1) 
     .Select((tr, ti) => tr + (increment * ti)) 
     .ToList() 
} 

Editar: Se ha cambiado al uso de la repetición, por lo que todavía se mantienen los valores de número no entero. Además, no se realiza ningún control de errores aquí, por lo que debe asegurarse de comprobar que increment no es 0 y que start < end * sign(increment). La razón para multiplicar el extremo por el signo de incremento es que si está incrementando en un número negativo, el final debe ser antes del inicio.

+3

+1 para mostrar realmente de dónde provienen los números (y para usar 'decimal') –

0

lo que haga, no utilice un tipo de datos de punto flotante (como double), que don' Trabajar para cosas como esta en nombre del comportamiento de redondeo. Vaya para decimal, o enteros con un factor. Para este último:

Decimal[] decs = new Decimal[500]; 
for (int i = 0; i < 500; i++){ 
    decs[i] = (new Decimal(i)/100)+1 ; 
} 
+0

no estoy de acuerdo con "lo que sea que hagas, no uses el tipo de datos de coma flotante" http://stackoverflow.com/questions/618535/what-is-the-difference-between-decimal-float-and-double-in -c – gsharp

+0

Iba a la definición más tradicional de 'punto flotante binario' de coma flotante;) – Martijn

9

La forma más sencilla es utilizar Enumerable.Range:

double[] result = Enumerable.Range(100, 500) 
        .Select(i => (double)i/100) 
        .ToArray(); 

(por lo tanto, eficiente en términos de facilidad de lectura y líneas de código)

+2

Buena respuesta. Una corrección: el rango que desea es Enumerable.Range (100, 600). – jdmcnair

+1

Probablemente debería basar todos los números del inicio, el final y el incremento, en lugar de calcularlos todos de antemano y pegar los números mágicos en el código. – Servy

+0

@jdmcnair: corregido, aunque su 'Rango (100, 600)' sería un rango de 1 a 7. Tenga en cuenta que lo anterior excluye '6.00', si lo necesita, tome 501. –

-1
var ia = new float[500]; //guesstimate 
var x = 0; 
for(float i =1; i <6.01; i+= 0.01){ 
    ia[x] = i; 
    x++; 
} 

Se podría multi-hilo esto para la velocidad, pero probablemente no vale la pena la sobrecarga a menos que planees ejecutar esto en un procesador realmente muy lento.

+0

Pero no puedo acceder a 'ia' fuera del ciclo, ¿o sí? ¿No es esto un problema de alcance? –

+0

No entiendo lo que quiere decir, ia no se definió dentro del bucle, por lo tanto, su alcance no está limitado al interior del bucle –

+0

Primero: eso no cabe en esa matriz. En segundo lugar, la conversión de estrechamiento implícito no funciona, necesita i + = 0.01F para esto, en tercer lugar, comenzará a recibir errores de redondeo en 1.52 – Martijn

2

utilizar un bucle con incrementos de 0,01:

List<decimal> myList = new List<decimal>(); 

for (decimal i = 1; i <= 6; i+=0.01) 
{ 
    myList.Add(i); 
} 
1

elegante

double[] v = Enumerable.Range(1, 600).Select(x => x * 0.01).ToArray(); 

eficiente

Use for loop 
4

me acaba de hacer una simple función.

public IEnumerable<decimal> GetValues(decimal start, decimal end, decimal increment) 
    { 
     for (decimal i = start; i <= end; i += increment) 
      yield return i; 
    } 

Luego puede convertir eso en una matriz, consultarla o hacer lo que quiera con ella.

 decimal[] result1 = GetValues(1.0m, 6.0m, .01m).ToArray(); 
     List<decimal> result2 = GetValues(1.0m, 6.0m, .01m).ToList(); 
     List<decimal> result3 = GetValues(1.0m, 6.0m, .01m).Where(d => d > 3 && d < 4).ToList(); 
+0

Me gusta esta solución de la mejor manera, ya que es simple y tiene muy poca sobrecarga en comparación con el uso de LINQ (no tiene que enumerar la colección dos veces, primero para construir el enumerable con rango/repetición, segundo para la función Seleccionar). – SPFiredrake

0

Puede resolverlo así. El método de solución devuelve un arreglo doble

double[] Solution(double min, int length, double increment) 
{ 
    double[] arr = new double[length]; 
    double value = min; 
    arr[0] = value; 
    for (int i = 1; i<length; i++) 
    { 
     value += increment; 
     arr[i] = value; 
    } 
    return arr; 
}