¿Cómo puedo obtener un recuento de la cantidad total de dígitos de un número en C #? Por ejemplo, el número 887979789 tiene 9 dígitos.
¿Cómo puedo obtener un recuento de la cantidad total de dígitos de un número en C #? Por ejemplo, el número 887979789 tiene 9 dígitos.
Respuestas:
Sin convertir a una cadena, puede intentar:
Math.Ceiling(Math.Log10(n));
Corrección siguiendo el comentario de ysap:
Math.Floor(Math.Log10(n) + 1);
n
se 0
puede devolver 1
:) Para manejar valores negativos, simplemente reemplácelos n
con Math.Abs(n)
.
Prueba esto:
myint.ToString().Length
Eso funciona ?
int
, así que supongo que eso no es un problema).
Cualquiera de los siguientes métodos de extensión funcionará. Todos ellos consideran el signo menos como un dígito y funcionan correctamente para todos los valores de entrada posibles. También funcionan para .NET Framework y .NET Core. Sin embargo, existen diferencias de rendimiento relevantes (que se analizan a continuación), según su elección de plataforma / marco.
Versión Int32:
public static class Int32Extensions
{
// IF-CHAIN:
public static int Digits_IfChain(this int n)
{
if (n >= 0)
{
if (n < 10) return 1;
if (n < 100) return 2;
if (n < 1000) return 3;
if (n < 10000) return 4;
if (n < 100000) return 5;
if (n < 1000000) return 6;
if (n < 10000000) return 7;
if (n < 100000000) return 8;
if (n < 1000000000) return 9;
return 10;
}
else
{
if (n > -10) return 2;
if (n > -100) return 3;
if (n > -1000) return 4;
if (n > -10000) return 5;
if (n > -100000) return 6;
if (n > -1000000) return 7;
if (n > -10000000) return 8;
if (n > -100000000) return 9;
if (n > -1000000000) return 10;
return 11;
}
}
// USING LOG10:
public static int Digits_Log10(this int n) =>
n == 0 ? 1 : (n > 0 ? 1 : 2) + (int)Math.Log10(Math.Abs((double)n));
// WHILE LOOP:
public static int Digits_While(this int n)
{
int digits = n < 0 ? 2 : 1;
while ((n /= 10) != 0) ++digits;
return digits;
}
// STRING CONVERSION:
public static int Digits_String(this int n) =>
n.ToString().Length;
}
Versión Int64:
public static class Int64Extensions
{
// IF-CHAIN:
public static int Digits_IfChain(this long n)
{
if (n >= 0)
{
if (n < 10L) return 1;
if (n < 100L) return 2;
if (n < 1000L) return 3;
if (n < 10000L) return 4;
if (n < 100000L) return 5;
if (n < 1000000L) return 6;
if (n < 10000000L) return 7;
if (n < 100000000L) return 8;
if (n < 1000000000L) return 9;
if (n < 10000000000L) return 10;
if (n < 100000000000L) return 11;
if (n < 1000000000000L) return 12;
if (n < 10000000000000L) return 13;
if (n < 100000000000000L) return 14;
if (n < 1000000000000000L) return 15;
if (n < 10000000000000000L) return 16;
if (n < 100000000000000000L) return 17;
if (n < 1000000000000000000L) return 18;
return 19;
}
else
{
if (n > -10L) return 2;
if (n > -100L) return 3;
if (n > -1000L) return 4;
if (n > -10000L) return 5;
if (n > -100000L) return 6;
if (n > -1000000L) return 7;
if (n > -10000000L) return 8;
if (n > -100000000L) return 9;
if (n > -1000000000L) return 10;
if (n > -10000000000L) return 11;
if (n > -100000000000L) return 12;
if (n > -1000000000000L) return 13;
if (n > -10000000000000L) return 14;
if (n > -100000000000000L) return 15;
if (n > -1000000000000000L) return 16;
if (n > -10000000000000000L) return 17;
if (n > -100000000000000000L) return 18;
if (n > -1000000000000000000L) return 19;
return 20;
}
}
// USING LOG10:
public static int Digits_Log10(this long n) =>
n == 0L ? 1 : (n > 0L ? 1 : 2) + (int)Math.Log10(Math.Abs((double)n));
// WHILE LOOP:
public static int Digits_While(this long n)
{
int digits = n < 0 ? 2 : 1;
while ((n /= 10L) != 0L) ++digits;
return digits;
}
// STRING CONVERSION:
public static int Digits_String(this long n) =>
n.ToString().Length;
}
Esta respuesta incluye pruebas realizadas para ambos tipos Int32
y Int64
, utilizando una matriz de números / 100.000.000
muestreados aleatoriamente . El conjunto de datos aleatorio se procesa previamente en una matriz antes de ejecutar las pruebas.int
long
También se ejecutaron pruebas de coherencia entre los 4 métodos diferentes, por MinValue
, casos fronterizos negativos, -1
, 0
, 1
, casos fronterizos positivas, MaxValue
y también para todo el conjunto de datos al azar. Ninguna prueba de consistencia falla para los métodos proporcionados anteriormente, EXCEPTO para el método LOG10 (esto se analiza más adelante).
Las pruebas se ejecutaron en .NET Framework 4.7.2
y .NET Core 2.2
; para plataformas x86
y x64
, en una máquina con procesador Intel de 64 bits, con Windows 10
y con VS2017 v.15.9.17
. Los siguientes 4 casos tienen el mismo efecto en los resultados de rendimiento:
.NET Framework (x86)
Platform = x86
Platform = AnyCPU
, Prefer 32-bit
está marcado en la configuración del proyecto
.NET Framework (x64)
Platform = x64
Platform = AnyCPU
, Prefer 32-bit
está desmarcado en la configuración del proyecto
.NET Core (x86)
"C:\Program Files (x86)\dotnet\dotnet.exe" bin\Release\netcoreapp2.2\ConsoleApp.dll
"C:\Program Files (x86)\dotnet\dotnet.exe" bin\x86\Release\netcoreapp2.2\ConsoleApp.dll
.NET Core (x64)
"C:\Program Files\dotnet\dotnet.exe" bin\Release\netcoreapp2.2\ConsoleApp.dll
"C:\Program Files\dotnet\dotnet.exe" bin\x64\Release\netcoreapp2.2\ConsoleApp.dll
Las pruebas de rendimiento siguientes producen una distribución uniforme de valores entre la amplia gama de valores que podría asumir un número entero. Esto significa que existe una probabilidad mucho mayor de probar valores con una gran cantidad de dígitos. En escenarios de la vida real, la mayoría de los valores pueden ser pequeños, por lo que IF-CHAIN debería funcionar aún mejor. Además, el procesador almacenará en caché y optimizará las decisiones de IF-CHAIN de acuerdo con su conjunto de datos.
Como @AlanSingfield señaló en la sección de comentarios, el método LOG10 tuvo que arreglarse con una conversión hacia double
adentro Math.Abs()
para el caso en que el valor de entrada es int.MinValue
o long.MinValue
.
Con respecto a las primeras pruebas de rendimiento que implementé antes de editar esta pregunta (ya tenía que ser editado un millón de veces), hubo un caso específico señalado por @ GyörgyKőszeg , en el que el método IF-CHAIN funciona más lento que el método LOG10.
Esto todavía sucede, aunque la magnitud de la diferencia se redujo mucho después de la solución del problema señalado por @AlanSingfield . Esta corrección (agregar una conversión a double
) provoca un error de cálculo cuando el valor de entrada es exactamente -999999999999999999
: el método LOG10 devuelve en 20
lugar de 19
. El método LOG10 también debe tener una if
protección para el caso en que el valor de entrada sea cero.
El método LOG10 es bastante complicado para trabajar con todos los valores, lo que significa que debe evitarlo. Si alguien encuentra una manera de hacer que funcione correctamente para todas las pruebas de coherencia a continuación, ¡publique un comentario!
El método WHILE también obtuvo una versión refactorizada reciente que es más rápida, pero aún es lenta Platform = x86
(no pude encontrar la razón por la cual, hasta ahora).
El método STRING es consistentemente lento: asigna con avidez demasiada memoria por nada. Curiosamente, en .NET Core, la asignación de cadenas parece ser mucho más rápida que en .NET Framework. Bueno saber.
El método IF-CHAIN debería superar a todos los demás métodos en el 99,99% de los casos; y, en mi opinión personal, es su mejor opción (considerando todos los ajustes necesarios para que el método LOG10 funcione correctamente y el mal desempeño de los otros dos métodos).
Finalmente, los resultados son:
Dado que estos resultados dependen del hardware, recomiendo de todos modos ejecutar las pruebas de rendimiento a continuación en su propia computadora si realmente necesita estar 100% seguro en su caso específico.
A continuación se muestra el código para la prueba de rendimiento y también la prueba de coherencia. El mismo código se usa para .NET Framework y .NET Core.
using System;
using System.Diagnostics;
namespace NumberOfDigits
{
// Performance Tests:
class Program
{
private static void Main(string[] args)
{
Console.WriteLine("\r\n.NET Core");
RunTests_Int32();
RunTests_Int64();
}
// Int32 Performance Tests:
private static void RunTests_Int32()
{
Console.WriteLine("\r\nInt32");
const int size = 100000000;
int[] samples = new int[size];
Random random = new Random((int)DateTime.Now.Ticks);
for (int i = 0; i < size; ++i)
samples[i] = random.Next(int.MinValue, int.MaxValue);
Stopwatch sw1 = new Stopwatch();
sw1.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_IfChain();
sw1.Stop();
Console.WriteLine($"IfChain: {sw1.ElapsedMilliseconds} ms");
Stopwatch sw2 = new Stopwatch();
sw2.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_Log10();
sw2.Stop();
Console.WriteLine($"Log10: {sw2.ElapsedMilliseconds} ms");
Stopwatch sw3 = new Stopwatch();
sw3.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_While();
sw3.Stop();
Console.WriteLine($"While: {sw3.ElapsedMilliseconds} ms");
Stopwatch sw4 = new Stopwatch();
sw4.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_String();
sw4.Stop();
Console.WriteLine($"String: {sw4.ElapsedMilliseconds} ms");
// Start of consistency tests:
Console.WriteLine("Running consistency tests...");
bool isConsistent = true;
// Consistency test on random set:
for (int i = 0; i < samples.Length; ++i)
{
int s = samples[i];
int a = s.Digits_IfChain();
int b = s.Digits_Log10();
int c = s.Digits_While();
int d = s.Digits_String();
if (a != b || c != d || a != c)
{
Console.WriteLine($"Digits({s}): IfChain={a} Log10={b} While={c} String={d}");
isConsistent = false;
break;
}
}
// Consistency test of special values:
samples = new int[]
{
0,
int.MinValue, -1000000000, -999999999, -100000000, -99999999, -10000000, -9999999, -1000000, -999999, -100000, -99999, -10000, -9999, -1000, -999, -100, -99, -10, -9, - 1,
int.MaxValue, 1000000000, 999999999, 100000000, 99999999, 10000000, 9999999, 1000000, 999999, 100000, 99999, 10000, 9999, 1000, 999, 100, 99, 10, 9, 1,
};
for (int i = 0; i < samples.Length; ++i)
{
int s = samples[i];
int a = s.Digits_IfChain();
int b = s.Digits_Log10();
int c = s.Digits_While();
int d = s.Digits_String();
if (a != b || c != d || a != c)
{
Console.WriteLine($"Digits({s}): IfChain={a} Log10={b} While={c} String={d}");
isConsistent = false;
break;
}
}
// Consistency test result:
if (isConsistent)
Console.WriteLine("Consistency tests are OK");
}
// Int64 Performance Tests:
private static void RunTests_Int64()
{
Console.WriteLine("\r\nInt64");
const int size = 100000000;
long[] samples = new long[size];
Random random = new Random((int)DateTime.Now.Ticks);
for (int i = 0; i < size; ++i)
samples[i] = Math.Sign(random.Next(-1, 1)) * (long)(random.NextDouble() * long.MaxValue);
Stopwatch sw1 = new Stopwatch();
sw1.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_IfChain();
sw1.Stop();
Console.WriteLine($"IfChain: {sw1.ElapsedMilliseconds} ms");
Stopwatch sw2 = new Stopwatch();
sw2.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_Log10();
sw2.Stop();
Console.WriteLine($"Log10: {sw2.ElapsedMilliseconds} ms");
Stopwatch sw3 = new Stopwatch();
sw3.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_While();
sw3.Stop();
Console.WriteLine($"While: {sw3.ElapsedMilliseconds} ms");
Stopwatch sw4 = new Stopwatch();
sw4.Start();
for (int i = 0; i < size; ++i) samples[i].Digits_String();
sw4.Stop();
Console.WriteLine($"String: {sw4.ElapsedMilliseconds} ms");
// Start of consistency tests:
Console.WriteLine("Running consistency tests...");
bool isConsistent = true;
// Consistency test on random set:
for (int i = 0; i < samples.Length; ++i)
{
long s = samples[i];
int a = s.Digits_IfChain();
int b = s.Digits_Log10();
int c = s.Digits_While();
int d = s.Digits_String();
if (a != b || c != d || a != c)
{
Console.WriteLine($"Digits({s}): IfChain={a} Log10={b} While={c} String={d}");
isConsistent = false;
break;
}
}
// Consistency test of special values:
samples = new long[]
{
0,
long.MinValue, -1000000000000000000, -999999999999999999, -100000000000000000, -99999999999999999, -10000000000000000, -9999999999999999, -1000000000000000, -999999999999999, -100000000000000, -99999999999999, -10000000000000, -9999999999999, -1000000000000, -999999999999, -100000000000, -99999999999, -10000000000, -9999999999, -1000000000, -999999999, -100000000, -99999999, -10000000, -9999999, -1000000, -999999, -100000, -99999, -10000, -9999, -1000, -999, -100, -99, -10, -9, - 1,
long.MaxValue, 1000000000000000000, 999999999999999999, 100000000000000000, 99999999999999999, 10000000000000000, 9999999999999999, 1000000000000000, 999999999999999, 100000000000000, 99999999999999, 10000000000000, 9999999999999, 1000000000000, 999999999999, 100000000000, 99999999999, 10000000000, 9999999999, 1000000000, 999999999, 100000000, 99999999, 10000000, 9999999, 1000000, 999999, 100000, 99999, 10000, 9999, 1000, 999, 100, 99, 10, 9, 1,
};
for (int i = 0; i < samples.Length; ++i)
{
long s = samples[i];
int a = s.Digits_IfChain();
int b = s.Digits_Log10();
int c = s.Digits_While();
int d = s.Digits_String();
if (a != b || c != d || a != c)
{
Console.WriteLine($"Digits({s}): IfChain={a} Log10={b} While={c} String={d}");
isConsistent = false;
break;
}
}
// Consistency test result:
if (isConsistent)
Console.WriteLine("Consistency tests are OK");
}
}
}
long.MaxValue
Log10 es significativamente mejor. ¿O es solo en .NET Core?
Int32
y Int64
generan diferentes conjuntos de datos, lo que puede explicar por qué Int64
fue más rápido que Int32
en algunos casos. Aunque, dentro de la Int32
prueba y dentro de la Int64
prueba, los conjuntos de datos no se modifican cuando se prueban los diferentes métodos de cálculo. Ahora, con respecto a .NET Core, dudo que haya alguna optimización mágica en la biblioteca de matemáticas que cambie estos resultados, pero me encantaría saber más sobre eso (mi respuesta ya es enorme, probablemente una de las más grandes en SO ;-)
for
bucles sobre enumerations
, I conjuntos de datos aleatorios pre-proceso, y evitar el uso de genéricos, Tareas Function<>
, Action<>
o cualquier marco de medición negro-caja). En resumen, manténgalo simple. También elimino todas las aplicaciones innecesarias (Skype, Windows Defender, deshabilito Anti-Virus, Chrome, caché de Microsoft Office, etc.).
No directamente en C #, pero la fórmula es: n = floor(log10(x)+1)
log10
es en la mayoría de los casos una función de biblioteca. ¿Por qué querría implementarlo usted mismo y qué problemas encuentra? log10(x) = log2(x) / log2(10)
, o en general logA(x) = logB(x) / logB(A)
.
Log10(0)
es -infinito. Log10 no se puede usar para calcular el número de dígitos de números negativos a menos que lo use Math.Abs()
antes de pasar el valor a Log10. Pero luego Math.Abs(int.MinValue)
arroja una excepción ( long.MinValue
también, en el caso de Int64). Si convertimos el número al doble antes de pasarlo a Log10, entonces funciona para casi todos los números excepto para -999999999999999999
(en el caso de Int64). ¿Conoce alguna fórmula para calcular la cantidad de dígitos que usa log10 y acepta cualquier valor int32 o int64 como entrada y genera solo valores válidos?
Las respuestas aquí ya funcionan para enteros sin signo, pero no he encontrado buenas soluciones para obtener el número de dígitos de decimales y dobles.
public static int Length(double number)
{
number = Math.Abs(number);
int length = 1;
while ((number /= 10) >= 1)
length++;
return length;
}
//number of digits in 0 = 1,
//number of digits in 22.1 = 2,
//number of digits in -23 = 2
Puede cambiar el tipo de entrada de double
a decimal
si la precisión importa, pero el decimal también tiene un límite.
La respuesta de Steve es correcta , pero no funciona para números enteros menores que 1.
Aquí una versión actualizada que funciona para negativos:
int digits = n == 0 ? 1 : Math.Floor(Math.Log10(Math.Abs(n)) + 1)
digits = n == 0 ? 1 : (int)Math.Floor(Math.Log10(Math.Abs(n)) + 1);
n = int.MinValue
.
Usar recursividad (a veces preguntado en entrevistas)
public int CountDigits(int number)
{
// In case of negative numbers
number = Math.Abs(number);
if (number >= 10)
return CountDigits(number / 10) + 1;
return 1;
}
number = int.MinValue
.
Aquí hay una implementación que utiliza una búsqueda binaria. Parece ser el más rápido hasta ahora en int32.
La implementación de Int64 se deja como ejercicio para el lector (!)
Intenté usar Array.BinarySearch en lugar de codificar el árbol, pero eso fue aproximadamente la mitad de la velocidad.
EDITAR: Una tabla de búsqueda es mucho más rápida que la búsqueda binaria, a expensas de usar más memoria. De manera realista, probablemente usaría la búsqueda binaria en producción, la tabla de búsqueda es muy compleja para una ganancia de velocidad que probablemente sea eclipsada por otras partes del software.
Lookup-Table: 439 ms
Binary-Search: 1069 ms
If-Chain: 1409 ms
Log10: 1145 ms
While: 1768 ms
String: 5153 ms
Versión de la tabla de búsqueda:
static byte[] _0000llll = new byte[0x10000];
static byte[] _FFFFllll = new byte[0x10001];
static sbyte[] _hhhhXXXXdigits = new sbyte[0x10000];
// Special cases where the high DWORD is not enough information to find out how
// many digits.
static ushort[] _lowordSplits = new ushort[12];
static sbyte[] _lowordSplitDigitsLT = new sbyte[12];
static sbyte[] _lowordSplitDigitsGE = new sbyte[12];
static Int32Extensions()
{
// Simple lookup tables for number of digits where value is
// 0000xxxx (0 .. 65535)
// or FFFFxxxx (-1 .. -65536)
precomputePositiveLo16();
precomputeNegativeLo16();
// Hiword is a little more complex
precomputeHiwordDigits();
}
private static void precomputeHiwordDigits()
{
int b = 0;
for(int hhhh = 0; hhhh <= 0xFFFF; hhhh++)
{
// For hiword hhhh, calculate integer value for loword of 0000 and FFFF.
int hhhh0000 = (unchecked(hhhh * 0x10000)); // wrap around on negatives
int hhhhFFFF = hhhh0000 + 0xFFFF;
// How many decimal digits for each?
int digits0000 = hhhh0000.Digits_IfChain();
int digitsFFFF = hhhhFFFF.Digits_IfChain();
// If same number of decimal digits, we know that when we see that hiword
// we don't have to look at the loword to know the right answer.
if(digits0000 == digitsFFFF)
{
_hhhhXXXXdigits[hhhh] = (sbyte)digits0000;
}
else
{
bool negative = hhhh >= 0x8000;
// Calculate 10, 100, 1000, 10000 etc
int tenToThePower = (int)Math.Pow(10, (negative ? digits0000 : digitsFFFF) - 1);
// Calculate the loword of the 10^n value.
ushort lowordSplit = unchecked((ushort)tenToThePower);
if(negative)
lowordSplit = unchecked((ushort)(2 + (ushort)~lowordSplit));
// Store the split point and digits into these arrays
_lowordSplits[b] = lowordSplit;
_lowordSplitDigitsLT[b] = (sbyte)digits0000;
_lowordSplitDigitsGE[b] = (sbyte)digitsFFFF;
// Store the minus of the array index into the digits lookup. We look for
// minus values and use these to trigger using the split points logic.
_hhhhXXXXdigits[hhhh] = (sbyte)(-b);
b++;
}
}
}
private static void precomputePositiveLo16()
{
for(int i = 0; i <= 9; i++)
_0000llll[i] = 1;
for(int i = 10; i <= 99; i++)
_0000llll[i] = 2;
for(int i = 100; i <= 999; i++)
_0000llll[i] = 3;
for(int i = 1000; i <= 9999; i++)
_0000llll[i] = 4;
for(int i = 10000; i <= 65535; i++)
_0000llll[i] = 5;
}
private static void precomputeNegativeLo16()
{
for(int i = 0; i <= 9; i++)
_FFFFllll[65536 - i] = 1;
for(int i = 10; i <= 99; i++)
_FFFFllll[65536 - i] = 2;
for(int i = 100; i <= 999; i++)
_FFFFllll[65536 - i] = 3;
for(int i = 1000; i <= 9999; i++)
_FFFFllll[65536 - i] = 4;
for(int i = 10000; i <= 65535; i++)
_FFFFllll[65536 - i] = 5;
}
public static int Digits_LookupTable(this int n)
{
// Split input into low word and high word.
ushort l = unchecked((ushort)n);
ushort h = unchecked((ushort)(n >> 16));
// If the hiword is 0000 or FFFF we have precomputed tables for these.
if(h == 0x0000)
{
return _0000llll[l];
}
else if(h == 0xFFFF)
{
return _FFFFllll[l];
}
// In most cases the hiword will tell us the number of decimal digits.
sbyte digits = _hhhhXXXXdigits[h];
// We put a positive number in this lookup table when
// hhhh0000 .. hhhhFFFF all have the same number of decimal digits.
if(digits > 0)
return digits;
// Where the answer is different for hhhh0000 to hhhhFFFF, we need to
// look up in a separate array to tell us at what loword the change occurs.
var splitIndex = (sbyte)(-digits);
ushort lowordSplit = _lowordSplits[splitIndex];
// Pick the correct answer from the relevant array, depending whether
// our loword is lower than the split point or greater/equal. Note that for
// negative numbers, the loword is LOWER for MORE decimal digits.
if(l < lowordSplit)
return _lowordSplitDigitsLT[splitIndex];
else
return _lowordSplitDigitsGE[splitIndex];
}
Versión de búsqueda binaria
public static int Digits_BinarySearch(this int n)
{
if(n >= 0)
{
if(n <= 9999) // 0 .. 9999
{
if(n <= 99) // 0 .. 99
{
return (n <= 9) ? 1 : 2;
}
else // 100 .. 9999
{
return (n <= 999) ? 3 : 4;
}
}
else // 10000 .. int.MaxValue
{
if(n <= 9_999_999) // 10000 .. 9,999,999
{
if(n <= 99_999)
return 5;
else if(n <= 999_999)
return 6;
else
return 7;
}
else // 10,000,000 .. int.MaxValue
{
if(n <= 99_999_999)
return 8;
else if(n <= 999_999_999)
return 9;
else
return 10;
}
}
}
else
{
if(n >= -9999) // -9999 .. -1
{
if(n >= -99) // -99 .. -1
{
return (n >= -9) ? 1 : 2;
}
else // -9999 .. -100
{
return (n >= -999) ? 3 : 4;
}
}
else // int.MinValue .. -10000
{
if(n >= -9_999_999) // -9,999,999 .. -10000
{
if(n >= -99_999)
return 5;
else if(n >= -999_999)
return 6;
else
return 7;
}
else // int.MinValue .. -10,000,000
{
if(n >= -99_999_999)
return 8;
else if(n >= -999_999_999)
return 9;
else
return 10;
}
}
}
}
Stopwatch sw0 = new Stopwatch();
sw0.Start();
for(int i = 0; i < size; ++i) samples[i].Digits_BinarySearch();
sw0.Stop();
Console.WriteLine($"Binary-Search: {sw0.ElapsedMilliseconds} ms");
Int64
implementación para LookUpTable? ¿O crees que es demasiado complicado implementarlo? Me gustaría ejecutar las pruebas de rendimiento más adelante en el conjunto completo.
int i = 855865264;
int NumLen = i.ToString().Length;
string.TrimStart('-')
mejor
Cree un método que devuelva todos los dígitos y otro que los cuente:
public static int GetNumberOfDigits(this long value)
{
return value.GetDigits().Count();
}
public static IEnumerable<int> GetDigits(this long value)
{
do
{
yield return (int)(value % 10);
value /= 10;
} while (value != 0);
}
Este me pareció el enfoque más intuitivo al abordar este problema. Probé elLog10
método primero debido a su aparente simplicidad, pero tiene una cantidad increíble de casos de esquina y problemas de precisión.
También encontré el if
cadena propuesta en la otra respuesta a un poco fea de ver.
Sé que este no es el método más eficiente, pero le brinda la otra extensión para devolver los dígitos también para otros usos (puede marcarlo private
si no necesita usarlo fuera de la clase).
Tenga en cuenta que no considera el signo negativo como un dígito.
convertir en cadena y luego puede contar el número de tatal de dígitos por el método .length. Me gusta:
String numberString = "855865264".toString();
int NumLen = numberString .Length;
Depende de lo que quieras hacer exactamente con los dígitos. Puede iterar a través de los dígitos comenzando desde el último hasta el primero de esta manera:
int tmp = number;
int lastDigit = 0;
do
{
lastDigit = tmp / 10;
doSomethingWithDigit(lastDigit);
tmp %= 10;
} while (tmp != 0);
%
para obtener el dígito y luego /=
cortarlo.
Si es solo para validar, podría hacer: 887979789 > 99999999
Suponiendo que su pregunta se refería a un int, lo siguiente también funciona para negativo / positivo y cero:
Math.Floor((decimal) Math.Abs(n)).ToString().Length