2010-03-24 29 views
19

En .NET, ¿cuál es la mejor manera de encontrar la longitud de un entero en caracteres si se representó como una cadena?Encontrar la longitud de cadena de un entero en .NET

p. Ej.

1 = 1 carácter
10 = 2 caracteres
99 = 2 caracteres
100 = 3 caracteres
1000 = 4 caracteres

La respuesta obvia es convertir el int a una cadena y obtener su pero quiero el mejor rendimiento posible sin la sobrecarga de crear una nueva cadena.

+9

Siempre mantenga el microsegundos libres que están tratando de ganar contra el tiempo de lectura cara de la pobre diablo (usted mismo, supongo) que tiene que leer y depurar ese código más tarde. – reinierpost

+4

@reinierpost no es una micro-optimización si dicho método se ejecuta, como, mil millones de veces en un ciclo llamado por miles de subprocesos diferentes. –

+0

¿Duplicado de este? http://stackoverflow.com/questions/679602/fastest-way-to-calculate-the-decimal-length-of-an-integer-net –

Respuesta

36

puede utilizar logartihms para calcular la longitud de la int:

public static int IntLength(int i) { 
    if (i <= 0) throw new ArgumentOutOfRangeException(); 

    return (int)Math.Floor(Math.Log10(i)) + 1; 
} 

se supera la prueba:

[Test] 
public void TestIntLength() { 
    Assert.AreEqual(1, IntLength(1)); 
    Assert.AreEqual(1, IntLength(9)); 
    Assert.AreEqual(2, IntLength(10)); 
    Assert.AreEqual(2, IntLength(99)); 
    Assert.AreEqual(3, IntLength(100)); 
    Assert.AreEqual(3, IntLength(999)); 
    Assert.AreEqual(4, IntLength(1000)); 
    Assert.AreEqual(10, IntLength(int.MaxValue)); 
} 

una la prueba rápida ha demostrado que el método de registro es 4 veces más rápido que el método de longitud int.ToString().

el método mostrado por GVS inferiores (con declaraciones if-) es otro 6 veces más rápido que el método de registro (!):

public static int IntLengthIf(int i) { 
    if (i < 10) return 1; 
    if (i < 100) return 2; 
    if (i < 1000) return 3; 
    if (i < 10000) return 4; 
    if (i < 100000) return 5; 
    if (i < 1000000) return 6; 
    if (i < 10000000) return 7; 
    if (i < 100000000) return 8; 
    if (i < 1000000000) return 9; 
    throw new ArgumentOutOfRangeException(); 
} 

aquí son los tiempos exactos de los números de 1 a 10 millones:

IntLengthToString: 4205ms 
IntLengthLog10: 1122ms 
IntLengthIf: 201ms 
+1

Para lidiar con números negativos, puede obtener el valor absoluto de i y luego agregar 1 al resultado de la función. –

+0

Si ya tiene una prueba rápida para esto, debe compararla con la solución de GvS. Eso debería ser interesante. –

+0

he actualizado mi respuesta. El método de GvS es mucho más rápido. – stmax

3

Usted podría utilizar algo como esto:

 int integer = 100; 

     int charachtersCount = 0; 
     while (integer > 0) 
     { 
      integer = integer/10; 
      charachtersCount++; 
     } 

Pero lo que realmente necesita para optimizar esto? Realidad preferiría usar cuerdas (se ve mucho mejor):

integer.ToString().Length 
+0

Buena solución, pero como dijiste yo dudaría de que el rendimiento sea bueno. Supongo que la conversión de cadenas es la mejor. –

-1

Si desea hacerlo por las matemáticas podría intentar esto:

int integer = 100 
int charCount = (int) Math.Ceiling(Math.Log10(integer+1)); 

Dudo que esto es mucho más rápido que la conversión de una cadena, aunque

1

Si usted necesita para hacer frente a los números negativos también, puede tomar stmax solution con un giro:

public static int IntLength(int i) { 
    if (i == 0) return 1; // no log10(0) 
    int n = (i < 0) ? 2 : 1; 
    i = (i < 0) ? -i : i; 

    return (int)Math.Floor(Math.Log10(i)) + n; 
} 
12

Si la entrada está en el rango 0-10000

if (i < 10) return 1; 
if (i < 100) return 2; 
if (i < 1000) return 3; 
if (i < 10000) return 4; 
// etc 
+1

Esta es la solución más simple, y se lee bien. Probablemente no pueda competir con un logaritmo optimizado de coma flotante. –

+2

No me molestaré en hacer la prueba, pero apuesto a que esta solución es más rápida que el logaritmo. Los registros requieren bastantes ciclos de reloj para calcular. –

+2

es 6 veces más rápido que mi método que usa registros. – stmax

1

que puede hacer:

int ndig = 1; 
if (n < 0){n = -n; ndig++;} 
if (n >= 100000000){n /= 100000000; ndig += 8;} 
if (n >=  10000){n /=  10000; ndig += 4;} 
if (n >=  100){n /=  100; ndig += 2;} 
if (n >=  10){n /=  10; ndig += 1;} 

o algo por el estilo. Toma 4 comparaciones y 0-4 divisiones.

(en 64 bits hay que añadir un quinto nivel.)

+0

Este tiene puntos inteligentes. Es un poco más lento que el derecho si pero me gusta. – JeffC

Cuestiones relacionadas