Comment puis-je compter le nombre total de chiffres d'un nombre en C #? Par exemple, le numéro 887979789 comporte 9 chiffres.
Comment puis-je compter le nombre total de chiffres d'un nombre en C #? Par exemple, le numéro 887979789 comporte 9 chiffres.
Réponses:
Sans convertir en une chaîne, vous pouvez essayer:
Math.Ceiling(Math.Log10(n));
Correction suite au commentaire d'Ysap:
Math.Floor(Math.Log10(n) + 1);
n
c'est 0
peut simplement retourner 1
:) Trop gérer les valeurs négatives, il suffit de les remplacer n
par Math.Abs(n)
.
Essaye ça:
myint.ToString().Length
Ça marche?
int
, donc je suppose que ce n'est pas un problème.)
L'une des méthodes d'extension suivantes fera l'affaire. Tous considèrent le signe moins comme un chiffre et fonctionnent correctement pour toutes les valeurs d'entrée possibles. Ils fonctionnent également pour .NET Framework et pour .NET Core. Il existe cependant des différences de performances pertinentes (décrites ci-dessous), en fonction de votre choix de plate-forme / cadre.
Version 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;
}
Version 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;
}
Cette réponse comprend des tests effectués pour les deux types Int32
et Int64
, en utilisant un tableau de nombres / 100.000.000
échantillonnés au hasard . L'ensemble de données aléatoires est prétraité dans un tableau avant d'exécuter les tests.int
long
Des tests de cohérence entre les 4 méthodes différentes ont également été exécutées, pour MinValue
, cas de frontières négatives, -1
, 0
, 1
, cas de frontière positifs, MaxValue
et aussi pour l'ensemble jeu de données aléatoire. Aucun test de cohérence n'échoue pour les méthodes fournies ci-dessus, SAUF pour la méthode LOG10 (cela sera discuté plus tard).
Les tests ont été exécutés sur .NET Framework 4.7.2
et .NET Core 2.2
; pour x86
et x64
plates - formes, sur une machine à processeur Intel 64 bits, avec Windows 10
et avec VS2017 v.15.9.17
. Les 4 cas suivants ont le même effet sur les résultats de performance:
.NET Framework (x86)
Platform = x86
Platform = AnyCPU
, Prefer 32-bit
est cochée dans les paramètres du projet
.NET Framework (x64)
Platform = x64
Platform = AnyCPU
, Prefer 32-bit
n'est pas cochée dans les paramètres du projet
.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
Les tests de performance ci-dessous produisent une distribution uniforme des valeurs parmi la large gamme de valeurs qu'un entier peut prendre. Cela signifie qu'il y a une chance beaucoup plus élevée de tester des valeurs avec un grand nombre de chiffres. Dans les scénarios réels, la plupart des valeurs peuvent être petites, donc l'IF-CHAIN devrait fonctionner encore mieux. De plus, le processeur mettra en cache et optimisera les décisions IF-CHAIN en fonction de votre ensemble de données.
Comme @AlanSingfield l'a souligné dans la section commentaire, la méthode LOG10 a dû être corrigée avec un casting vers l' double
intérieur Math.Abs()
pour le cas où la valeur d'entrée est int.MinValue
ou long.MinValue
.
En ce qui concerne les premiers tests de performances que j'ai mis en œuvre avant de modifier cette question (elle devait déjà être modifiée un million de fois), il y avait un cas spécifique signalé par @ GyörgyKőszeg , dans lequel la méthode IF-CHAIN fonctionne plus lentement que la méthode LOG10.
Cela se produit toujours, bien que l'ampleur de la différence soit devenue beaucoup plus faible après le correctif du problème signalé par @AlanSingfield . Ce correctif (ajouter un cast à double
) provoque une erreur de calcul lorsque la valeur d'entrée est exactement -999999999999999999
: la méthode LOG10 renvoie à la 20
place de 19
. La méthode LOG10 doit également avoir une if
garde pour le cas où la valeur d'entrée est zéro.
La méthode LOG10 est assez délicate à utiliser pour toutes les valeurs, ce qui signifie que vous devez l'éviter. Si quelqu'un trouve un moyen de le faire fonctionner correctement pour tous les tests de cohérence ci-dessous, veuillez poster un commentaire!
La méthode WHILE a également obtenu une version refactorisée récente qui est plus rapide, mais elle est encore lente Platform = x86
(je n'ai pas pu trouver la raison pour laquelle, jusqu'à présent).
La méthode STRING est toujours lente: elle alloue avec gourmandise trop de mémoire pour rien. Fait intéressant, dans .NET Core, l'allocation de chaînes semble être beaucoup plus rapide que dans .NET Framework. Bon à savoir.
La méthode IF-CHAIN devrait surpasser toutes les autres méthodes dans 99,99% des cas; et, à mon avis personnel, est votre meilleur choix (compte tenu de tous les ajustements nécessaires pour que la méthode LOG10 fonctionne correctement, et des mauvaises performances des deux autres méthodes).
Enfin, les résultats sont:
Étant donné que ces résultats dépendent du matériel, je recommande quand même d'exécuter les tests de performances ci-dessous sur votre propre ordinateur si vous avez vraiment besoin d'être sûr à 100% dans votre cas spécifique.
Vous trouverez ci-dessous le code du test de performance, ainsi que le test de cohérence. Le même code est utilisé pour .NET Framework et .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, c'est nettement mieux. Ou est-ce juste dans .NET Core?
Int32
et Int64
génèrent différents ensembles de données, ce qui peut expliquer pourquoi ils Int64
sont devenus plus rapides que Int32
dans certains cas. Cependant, dans le Int32
test et dans le Int64
test, les ensembles de données ne sont pas modifiés lors du test des différentes méthodes de calcul. Maintenant en ce qui concerne .NET Core, je doute qu'il y ait une optimisation magique dans la bibliothèque Math qui changerait ces résultats, mais j'aimerais en savoir plus à ce sujet (ma réponse est déjà énorme, probablement l'une des plus importantes de SO ;-)
for
boucles sur enumerations
, I ensembles de données aléatoires pré-processus, et éviter l'utilisation des médicaments génériques, les tâches Function<>
, Action<>
ou tout cadre de mesure noir boxed). En résumé, restez simple. Je tue également toutes les applications inutiles (Skype, Windows Defender, désactiver l'antivirus, Chrome, le cache Microsoft Office, etc.).
Pas directement C #, mais la formule est: n = floor(log10(x)+1)
log10
est dans la plupart des cas une fonction de bibliothèque. Pourquoi voudriez-vous le mettre en œuvre vous-même et quels problèmes rencontrez-vous? log10(x) = log2(x) / log2(10)
, ou généralement logA(x) = logB(x) / logB(A)
.
Log10(0)
est -infinity. Log10 ne peut pas être utilisé pour calculer le nombre de chiffres de nombres négatifs à moins que vous Math.Abs()
ne l'utilisiez avant de passer la valeur à Log10. Mais Math.Abs(int.MinValue)
lance ensuite une exception ( long.MinValue
aussi, dans le cas d'Int64). Si nous convertissons le nombre en double avant de le passer à Log10, cela fonctionne pour presque tous les nombres sauf pour -999999999999999999
(dans le cas de Int64). Connaissez-vous une formule pour calculer le nombre de chiffres qui utilise log10 et accepte toute valeur int32 ou int64 comme entrée et ne produit que des valeurs valides?
Les réponses déjà ici fonctionnent pour les entiers non signés, mais je n'ai pas trouvé de bonnes solutions pour obtenir le nombre de chiffres à partir des décimales et des doubles.
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
Vous pouvez changer le type d'entrée de double
à decimal
si la précision est importante, mais décimal a également une limite.
La réponse de Steve est correcte , mais cela ne fonctionne pas pour les entiers inférieurs à 1.
Voici une version mise à jour qui fonctionne pour les négatifs:
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
.
Utilisation de la récursivité (parfois posée lors des entretiens)
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
.
Voici une implémentation utilisant une recherche binaire. Semble être le plus rapide à ce jour sur int32.
L'implémentation Int64 est laissée comme un exercice pour le lecteur (!)
J'ai essayé d'utiliser Array.BinarySearch plutôt que de coder en dur l'arbre, mais c'était environ la moitié de la vitesse.
EDIT: Une table de recherche est beaucoup plus rapide que la recherche binaire, au détriment de l'utilisation de plus de mémoire. En réalité, j'utiliserais probablement la recherche binaire en production, la table de recherche est beaucoup plus complexe pour un gain de vitesse susceptible d'être éclipsé par d'autres parties du logiciel.
Lookup-Table: 439 ms
Binary-Search: 1069 ms
If-Chain: 1409 ms
Log10: 1145 ms
While: 1768 ms
String: 5153 ms
Version de la table de recherche:
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];
}
Version de recherche binaire
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
implémentation de LookUpTable? Ou pensez-vous que c'est trop compliqué à mettre en œuvre? J'aimerais exécuter les tests de performances plus tard sur l'ensemble complet.
int i = 855865264;
int NumLen = i.ToString().Length;
string.TrimStart('-')
mieux
Créez une méthode qui renvoie tous les chiffres et une autre qui les compte:
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);
}
Cela me semblait être l'approche la plus intuitive pour aborder ce problème. J'ai d'abord essayé la Log10
méthode en raison de son apparente simplicité, mais elle présente une quantité insensée de boîtiers d'angle et de problèmes de précision.
J'ai aussi trouvé le if
chaîne proposée dans l'autre réponse un peu moche à regarder.
Je sais que ce n'est pas la méthode la plus efficace, mais elle vous donne l'autre extension pour renvoyer les chiffres également pour d'autres utilisations (vous pouvez simplement la marquer private
si vous n'avez pas besoin de l'utiliser en dehors de la classe).
Gardez à l'esprit qu'il ne considère pas le signe négatif comme un chiffre.
convertir en chaîne et puis vous pouvez compter le nombre tatal de chiffre par la méthode .length. Comme:
String numberString = "855865264".toString();
int NumLen = numberString .Length;
Cela dépend de ce que vous voulez faire exactement avec les chiffres. Vous pouvez parcourir les chiffres du dernier au premier comme ceci:
int tmp = number;
int lastDigit = 0;
do
{
lastDigit = tmp / 10;
doSomethingWithDigit(lastDigit);
tmp %= 10;
} while (tmp != 0);
%
pour obtenir le chiffre, puis /=
pour le réduire.
Si ce n'est que pour valider, vous pouvez faire: 887979789 > 99999999
En supposant que votre question se réfère à un entier, ce qui suit fonctionne pour négatif / positif et zéro également:
Math.Floor((decimal) Math.Abs(n)).ToString().Length