Comment convertir un Int en Ssortingng en C # sans utiliser ToSsortingng ()?

Convertissez l’argument int suivant en une chaîne sans utiliser de fonctionnalité native toSsortingng.

public ssortingng integerToSsortingng(int integerPassedIn){ //Your code here } 

Comme tout hérite de Object et Object a une méthode ToSsortingng() , comment convertissez-vous un int en une ssortingng sans utiliser la méthode ToSsortingng() native?

Le problème avec la concaténation de chaînes de caractères est qu’elle appellera ToSsortingng() jusqu’à ce qu’elle en rencontre une ou frappe la classe Object .

Comment convertir un entier en une chaîne en C # sans utiliser ToSsortingng() ?

Quelque chose comme ça:

 public ssortingng IntToSsortingng(int a) { var chars = new[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; var str = ssortingng.Empty; if (a == 0) { str = chars[0]; } else if (a == int.MinValue) { str = "-2147483648"; } else { bool isNegative = (a < 0); if (isNegative) { a = -a; } while (a > 0) { str = chars[a % 10] + str; a /= 10; } if (isNegative) { str = "-" + str; } } return str; } 

Mise à jour: Voici une autre version qui est plus courte et devrait donner de bien meilleurs résultats, car elle élimine toute concaténation de chaînes en faveur de la manipulation d’un tableau de longueur fixe. Il supporte les bases jusqu’à 16, mais il serait facile de l’étendre à des bases plus élevées. Il pourrait probablement être amélioré davantage:

 public ssortingng IntToSsortingng(int a, int radix) { var chars = "0123456789ABCDEF".ToCharArray(); var str = new char[32]; // maximum number of chars in any base var i = str.Length; bool isNegative = (a < 0); if (a <= 0) // handles 0 and int.MinValue special cases { str[--i] = chars[-(a % radix)]; a = -(a / radix); } while (a != 0) { str[--i] = chars[a % radix]; a /= radix; } if (isNegative) { str[--i] = '-'; } return new string(str, i, str.Length - i); } 

C’est la solution que j’utilise toujours:

  public static ssortingng numberBaseChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; public static ssortingng IntToSsortingngWithBase(int n, int b) { return IntToSsortingngWithBase(n, b, 1); } public static ssortingng IntToSsortingngWithBase(int n, int b, int minDigits) { if (minDigits < 1) minDigits = 1; if (n == 0) return new string('0', minDigits); string s = ""; if ((b < 2) || (b > numberBaseChars.Length)) return s; bool neg = false; if ((b == 10) && (n < 0)) { neg = true; n = -n; } uint N = (uint)n; uint B = (uint)b; while ((N > 0) | (minDigits-- > 0)) { s = numberBaseChars[(int)(N % B)] + s; N /= B; } if (neg) s = "-" + s; return s; } 

Cela semble assez compliqué mais a les caractéristiques suivantes:

  • Prise en charge de radix 2 à 36
  • Traite les valeurs négatives
  • Nombre total facultatif de chiffres

Je ne suis pas vraiment convaincu que l’ operator + concaténation operator + appelle ToSsortingng , mais si cela est effectivement vrai, vous pouvez éviter les deux en procédant comme suit:

 if (a == 0) return "0"; /* Negative maxint doesn't have a corresponding positive value, so handle it * as a special case. Thanks to @Daniel for pointing this out. */ if (a == 0x80000000) return "-2147483648"; List l = new List(); bool negative = false; if (a < 0) { negative = true; a *= -1; } while (a > 0) { l.Add('0' + (char)(a % 10)); a /= 10; } if (negative) l.Add('-'); l.Reverse(); return new Ssortingng(l.ToArray()); 

L’entier est traité du chiffre le moins significatif au plus significatif. Un seul chiffre est calculé modulo 10 (% 10), qui est ensuite ajouté à la valeur de caractère “0”. Cela se traduit par l’un des caractères ‘0’, ‘1’, …, ‘9’.

Les chiffres sont poussés sur une stack car ils doivent être présentés dans l’ordre inverse au fur et à mesure de leur traitement (chiffre le plus significatif au chiffre le moins significatif). Faire cela comme cela au lieu de répéter plusieurs fois les chiffres sur une chaîne pourrait être plus efficace, mais comme le nombre de chiffres est assez faible, vous devrez effectuer un test de performance pour être sûr.

Un traitement supplémentaire est nécessaire pour gérer les nombres non positifs.

 public ssortingng IntToSsortingng(int a) { if (a == 0) return "0"; if (a == int.MinValue) return "-2147483648"; var isNegative = false; if (a < 0) { a = -a; isNegative = true; } var stack = new Stack(); while (a != 0) { var c = a%10 + '0'; stack.Push((char) c); a /= 10; } if (isNegative) stack.Push('-'); return new ssortingng(stack.ToArray()); } 

Ma première version a utilisé un SsortingngBuilder pour créer la chaîne à partir du tableau de caractères, mais l’obtention de la chaîne “hors de” SsortingngBuilder nécessite un appel à la méthode appelée ToSsortingng . De toute évidence, cette méthode ne fait pas de conversion de chaîne en chaîne, ce qui pour moi correspond à cette question.

Mais pour prouver que vous pouvez créer une chaîne sans appeler ToSsortingng je suis passé à l’utilisation d’un constructeur de ssortingng que je suppose également plus efficace que d’utiliser un SsortingngBuilder .

Et si ToSsortingng sous quelque forme que ce soit est interdit, vous ne pouvez pas utiliser la concaténation de chaînes comme indiqué dans la documentation de ssortingng.Concat :

La méthode concatène arg0 et arg1 en appelant la méthode sans paramètre ToSsortingng de arg0 et arg1; il n’ajoute aucun délimiteur.

exécutant donc s += '1' appellera '1'.ToSsortingng() . Mais pour moi, ce n’est pas important. La partie importante est la façon dont vous convertissez un int en chaîne.

Viser une version plus courte et une version utilisant Math.DivRem :

 ssortingng IntToSsortingng(int a) { if (a == int.MinValue) return "-2147483648"; if (a < 0) return "-" + IntToString(-a); if (a == 0) return "0"; var s = ""; do { int r; a = Math.DivRem(a, 10, out r); s = new string((char)(r + (int)'0'), 1) + s; } while (a > 0); return s; } 

L’utilisation du new ssortingng(..., 1) est simplement un moyen de satisfaire à l’exigence de l’OP selon laquelle ToSsortingng ne doit être appelé sur rien.

Voici mes sockets en compte à l’aide de l’itération et de la récursivité avec l’parsing du temps d’exécution.

 public static class IntegerToSsortingng { static char[] d = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray(); public static ssortingng Iteration(int num, int radix = 10) { if (num == 0) return "0"; if (num < 0) return "-" + Iteration(Math.Abs(num)); var r = new List(); while (num > 0) { r.Insert(0, d[num % radix]); num /= radix; } return new ssortingng(r.ToArray()); } public static ssortingng Recursion(int num, int radix = 10) { if (num == 0) return "0"; if (num < 0) return "-" + Recursion(Math.Abs(num)); return (num > radix - 1 ? Recursion(num / radix) : "") + d[num % radix]; } } 

Points clés

  • Gère la base 2 jusqu’à 36 ( CAVEAT: vous devez vous assurer que votre base est correcte car il n’y a pas de gestion des exceptions.
  • La méthode de récursivité ne dure que 3 lignes! (code style golf)

Une parsing

Ce qui suit est l’parsing de l’exécution des deux méthodes par rapport à la norme ToSsortingng() sur mon ordinateur.

 50 runs of 100000 items per set Running Time: Iteration: 00:00:02.3459591 (00:00:00.0469191 avg) Recursion: 00:00:02.1359731 (00:00:00.0427194 avg) Standard : 00:00:00.4271253 (00:00:00.0085425 avg) Ratios: | Iter | Rec | Std -----+------+------+----- Iter | 1.00 | 0.91 | 0.18 Rec | 1.10 | 1.00 | 0.20 Std | 5.49 | 5.00 | 1.00 

Les résultats indiquent que les méthodes d’itération et de récursivité sont 5,49 fois moins rapides que la méthode ToSsortingng() standard.

Et voici le code que j’ai utilisé pour l’parsing:

 class Program { static void Main(ssortingng[] args) { var r = new Random(); var sw = new System.Diagnostics.Stopwatch(); var loop = new List(); var recr = new List(); var std = new List(); var setSize = 100000; var runs = 50; Console.WriteLine("{0} runs of {1} items per set", runs, setSize); for (int j = 0; j < runs; j++) { // create number set var numbers = Enumerable.Range(1, setSize) .Select(s => r.Next(int.MinValue, int.MaxValue)) .ToArray(); // loop sw.Start(); for (int i = 0; i < setSize; i++) IntegerToString.Iteration(numbers[i]); sw.Stop(); loop.Add(sw.ElapsedTicks); // recursion sw.Reset(); sw.Start(); for (int i = 0; i < setSize; i++) IntegerToString.Recursion(numbers[i]); sw.Stop(); recr.Add(sw.ElapsedTicks); // standard sw.Reset(); sw.Start(); for (int i = 0; i < setSize; i++) numbers[i].ToString(); sw.Stop(); std.Add(sw.ElapsedTicks); } Console.WriteLine(); Console.WriteLine("Running Time:"); Console.WriteLine("Iteration: {0} ({1} avg)", TimeSpan.FromTicks(loop.Sum()), TimeSpan.FromTicks((int)loop.Average())); Console.WriteLine("Recursion: {0} ({1} avg)", TimeSpan.FromTicks(recr.Sum()), TimeSpan.FromTicks((int)recr.Average())); Console.WriteLine("Standard : {0} ({1} avg)", TimeSpan.FromTicks(std.Sum()), TimeSpan.FromTicks((int)std.Average())); double lSum = loop.Sum(); double rSum = recr.Sum(); double sSum = std.Sum(); Console.WriteLine(); Console.WriteLine("Ratios: \n" + " | Iter | Rec | Std \n" + "-----+------+------+-----"); foreach (var div in new[] { new {n = "Iter", t = lSum}, new {n = "Rec ", t = rSum}, new {n = "Std ", t = sSum}}) Console.WriteLine("{0} | {1:0.00} | {2:0.00} | {3:0.00}", div.n, lSum / div.t, rSum / div.t, sSum / div.t); Console.ReadLine(); } 

vous pouvez convertir n’importe quel chiffre en un caractère comme celui-ci

 byte = (char)(byte)(digit+48) 

Le nombre magique 48 est la valeur ASCII du caractère 0 et ils sont séquentiels dans le tableau ASCII. Vous pouvez donc simplement append le chiffre pour obtenir la valeur correspondante dans le tableau ASCII. et vous pouvez obtenir les chiffres dans l’entier itérativement en utilisant l’opérateur de module % Emprunter la structure générale de pswg que vous obtiendriez

 public ssortingng IntToSsortingng(int a) { var str = ssortingng.Empty; bool isNegative = false; if (a < 0) { isNegative = true; a = -a; } do { str = (char)(byte)((a % 10) + 48) + str; a /= 10; } while(a > 0); return isNegative ? '-' + str : str } 
  public static ssortingng integerToSsortingng(int integerPassedIn) { if (integerPassedIn == 0) return "0"; var negative = integerPassedIn < 0; var res = new List(); while(integerPassedIn != 0) { res.Add((char)(48 + Math.Abs(integerPassedIn % 10))); integerPassedIn /= 10; } res.Reverse(); if (negative) res.Insert(0, '-'); return new ssortingng(res.ToArray()); } 

Récursivité:

  public static ssortingng integerToSsortingng(int integerPassedIn) { ICollection res = new List(); IntToSsortingngRecusion(integerPassedIn, res); if (integerPassedIn < 0) res.Add('-'); return new string(res.Reverse().ToArray()).PadLeft(1,'0'); } static void IntToStringRecusion(int integerPassedIn, ICollection array) { if (integerPassedIn == 0) return; array.Add((char)(48 + Math.Abs(integerPassedIn % 10))); IntToSsortingngRecusion(integerPassedIn / 10, array); } 

Si c ++, alors:

 public ssortingng IntToSsortingng(int a){ char rc[20]; int x = a; if(a < 0) x = -x; char *p = rc + 19; *p = 0; do *--p = (x % 10) | '0'; while(x /= 10); if(a < 0) *--p = '-'; return string(p); }