Como posso obter uma contagem do número total de dígitos de um número em C #? Por exemplo, o número 887979789 tem 9 dígitos.
Como posso obter uma contagem do número total de dígitos de um número em C #? Por exemplo, o número 887979789 tem 9 dígitos.
Respostas:
Sem converter para uma string, você pode tentar:
Math.Ceiling(Math.Log10(n));
Correção após o comentário de ysap:
Math.Floor(Math.Log10(n) + 1);
n
é 0
pode simplesmente voltar 1
:) valores negativos trabalhar também apenas substituir n
com Math.Abs(n)
.
Experimente isto:
myint.ToString().Length
Isso funciona ?
int
, então presumo que isso não seja um problema.)
Qualquer um dos seguintes métodos de extensão fará o trabalho. Todos eles consideram o sinal de menos como um dígito e funcionam corretamente para todos os valores de entrada possíveis. Eles também funcionam para .NET Framework e .NET Core. No entanto, existem diferenças de desempenho relevantes (discutidas abaixo), dependendo da sua escolha de Plataforma / Estrutura.
Versão 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;
}
Versão 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;
}
Essa resposta inclui testes executados para os tipos Int32
e Int64
, usando uma matriz de números / 100.000.000
amostras aleatoriamente . O conjunto de dados aleatório é pré-processado em uma matriz antes de executar os testes.int
long
Testes de consistência entre os 4 métodos diferentes também foram executados, para MinValue
, casos de fronteira negativos, -1
, 0
, 1
, casos de fronteira positivos, MaxValue
e também para todo o conjunto de dados aleatório. Nenhum teste de consistência falha para os métodos fornecidos acima, EXCETO para o método LOG10 (isso será discutido mais tarde).
Os testes foram executados em .NET Framework 4.7.2
e .NET Core 2.2
; para plataformas x86
e x64
, em uma máquina com processador Intel de 64 bits, com Windows 10
e com VS2017 v.15.9.17
. Os 4 casos a seguir têm o mesmo efeito nos resultados de desempenho:
.NET Framework (x86)
Platform = x86
Platform = AnyCPU
, Prefer 32-bit
é verificado nas configurações do projeto
.NET Framework (x64)
Platform = x64
Platform = AnyCPU
, Prefer 32-bit
está desmarcado nas configurações do projeto
.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
Os testes de desempenho abaixo produzem uma distribuição uniforme de valores entre a ampla gama de valores que um inteiro pode assumir. Isso significa que há uma chance muito maior de valores de teste com uma grande contagem de dígitos. Em cenários da vida real, a maioria dos valores pode ser pequena, então o IF-CHAIN deve ter um desempenho ainda melhor. Além disso, o processador armazenará em cache e otimizará as decisões IF-CHAIN de acordo com seu conjunto de dados.
Como @AlanSingfield apontou na seção de comentários, o método LOG10 teve que ser corrigido com uma conversão para double
dentro Math.Abs()
para o caso em que o valor de entrada é int.MinValue
ou long.MinValue
.
Em relação aos primeiros testes de desempenho que implementei antes de editar esta questão (ela já tinha que ser editada um milhão de vezes), houve um caso específico apontado por @ GyörgyKőszeg , no qual o método IF-CHAIN tem desempenho mais lento do que o método LOG10.
Isso ainda acontece, embora a magnitude da diferença tenha se tornado muito menor após a correção do problema apontado por @AlanSingfield . Esta correção (adicionar uma conversão a double
) causa um erro de cálculo quando o valor de entrada é exatamente -999999999999999999
: o método LOG10 retorna em 20
vez de 19
. O método LOG10 também deve ter uma if
proteção para o caso em que o valor de entrada é zero.
O método LOG10 é bastante complicado para funcionar para todos os valores, o que significa que você deve evitá-lo. Se alguém encontrar uma maneira de fazer funcionar corretamente para todos os testes de consistência abaixo, poste um comentário!
O método WHILE também ganhou uma versão refatorada recente que é mais rápida, mas ainda é lenta para Platform = x86
(não consegui descobrir o motivo, até agora).
O método STRING é consistentemente lento: ele aloca avidamente muita memória para nada. Curiosamente, no .NET Core, a alocação de strings parece ser muito mais rápida do que no .NET Framework. Bom saber.
O método IF-CHAIN deve superar todos os outros métodos em 99,99% dos casos; e, na minha opinião pessoal, é a sua melhor escolha (considerando todos os ajustes necessários para que o método LOG10 funcione corretamente e o mau desempenho dos outros dois métodos).
Finalmente, os resultados são:
Como esses resultados dependem do hardware, recomendo mesmo assim executar os testes de desempenho abaixo em seu próprio computador se você realmente precisar ter 100% de certeza em seu caso específico.
Abaixo está o código para o teste de desempenho e também o teste de consistência. O mesmo código é usado para .NET Framework e .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 é significativamente melhor. Ou está apenas no .NET Core?
Int32
e Int64
geram conjuntos de dados diferentes, o que pode explicar por que Int64
ficou mais rápido do que Int32
em alguns casos. Embora, dentro do Int32
teste e dentro do Int64
teste, os conjuntos de dados não sejam alterados ao testar os diferentes métodos de cálculo. Agora, em relação ao .NET Core, duvido que haja alguma otimização mágica na biblioteca de matemática que mudaria esses resultados, mas adoraria ouvir mais sobre isso (minha resposta já é enorme, provavelmente uma das maiores em SO ;-)
for
laços mais enumerations
, eu pré-processar conjuntos de dados aleatórios, e evitar o uso de genéricos, Tarefas Function<>
, Action<>
ou qualquer estrutura de medição black-box). Em resumo, mantenha as coisas simples. Eu também mato todos os aplicativos desnecessários (Skype, Windows Defender, desabilito o antivírus, Chrome, cache do Microsoft Office, etc).
Não diretamente C #, mas a fórmula é: n = floor(log10(x)+1)
log10
é na maioria dos casos uma função de biblioteca. Por que você deseja implementá-lo sozinho e quais problemas você encontra? log10(x) = log2(x) / log2(10)
, ou geralmente logA(x) = logB(x) / logB(A)
.
Log10(0)
é -infinity. Log10 não pode ser usado para calcular o número de dígitos de números negativos, a menos que você use Math.Abs()
antes de passar o valor para Log10. Mas então Math.Abs(int.MinValue)
lança uma exceção ( long.MinValue
também, no caso de Int64). Se lançarmos o número para o dobro antes de passá-lo para Log10, ele funcionará para quase todos os números, exceto para -999999999999999999
(no caso de Int64). Você conhece alguma fórmula para calcular o número de dígitos que usa log10 e aceita qualquer valor int32 ou int64 como entrada e produz apenas valores válidos?
As respostas já aqui funcionam para inteiros sem sinal, mas não encontrei boas soluções para obter o número de dígitos de decimais e duplos.
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
Você pode alterar o tipo de entrada de double
para decimal
se a precisão for importante, mas decimal também tem um limite.
A resposta de Steve está correta , mas não funciona para inteiros menores que 1.
Aqui está uma versão atualizada 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
.
Usando recursão (às vezes perguntado em 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
.
static void Main(string[] args)
{
long blah = 20948230498204;
Console.WriteLine(blah.ToString().Length);
}
-1
= 2
Aqui está uma implementação usando uma pesquisa binária. Parece ser o mais rápido até agora na int32.
A implementação de Int64 é deixada como um exercício para o leitor (!)
Tentei usar Array.BinarySearch em vez de codificar a árvore, mas isso foi cerca da metade da velocidade.
EDIT: Uma tabela de pesquisa é muito mais rápida do que a pesquisa binária, ao custo de usar mais memória. Realisticamente, eu provavelmente usaria a pesquisa binária na produção, a tabela de pesquisa é muito complexa para um ganho de velocidade que provavelmente será ofuscado por outras partes do software.
Lookup-Table: 439 ms
Binary-Search: 1069 ms
If-Chain: 1409 ms
Log10: 1145 ms
While: 1768 ms
String: 5153 ms
Versão da tabela de pesquisa:
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];
}
Versão de pesquisa binária
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
implementação para LookUpTable? Ou você acha que é muito complicado de implementar? Eu gostaria de executar os testes de desempenho mais tarde no conjunto completo.
int i = 855865264;
int NumLen = i.ToString().Length;
string.TrimStart('-')
melhor
Crie um método que retorne todos os dígitos e outro que os conte:
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);
}
Essa parecia a abordagem mais intuitiva para mim ao lidar com esse problema. Eu tentei oLog10
método primeiro devido à sua aparente simplicidade, mas ele tem uma quantidade absurda de casos de canto e problemas de precisão.
Eu também encontrei o if
cadeia proposta na outra resposta para um pouco feia de se olhar.
Eu sei que este não é o método mais eficiente, mas fornece a outra extensão para retornar os dígitos também para outros usos (você pode apenas marcá-lo private
se não precisar usá-lo fora da classe).
Lembre-se de que ele não considera o sinal negativo como um dígito.
converter em string e então você pode contar o número tatal de dígitos pelo método .length. Gostar:
String numberString = "855865264".toString();
int NumLen = numberString .Length;
Depende do que exatamente você deseja fazer com os dígitos. Você pode iterar através dos dígitos, começando do último para o primeiro, assim:
int tmp = number;
int lastDigit = 0;
do
{
lastDigit = tmp / 10;
doSomethingWithDigit(lastDigit);
tmp %= 10;
} while (tmp != 0);
%
para obter o dígito e, em seguida, /=
reduzi-lo.
Se for apenas para validar, você pode fazer: 887979789 > 99999999
Supondo que sua pergunta se referisse a um int, o seguinte funciona para negativo / positivo e zero também:
Math.Floor((decimal) Math.Abs(n)).ToString().Length