How do I convert an Int to a String in C# without using ToString()?

前端 未结 10 1170
耶瑟儿~
耶瑟儿~ 2020-12-12 13:49

Convert the following int argument into a string without using any native toString functionality.

public string integerToString(int integerPas         


        
相关标签:
10条回答
  • 2020-12-12 14:09

    Here are my takes on it using iteration and recursion with run time analysis.

    public static class IntegerToString
    {
        static char[] d = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
    
        public static string Iteration(int num, int radix = 10)
        {
            if (num == 0) return "0";
            if (num < 0) return "-" + Iteration(Math.Abs(num));
            var r = new List<char>();
            while (num > 0)
            {
                r.Insert(0, d[num % radix]);
                num /= radix;
            }
            return new string(r.ToArray());
        }
    
        public static string 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];
        }
    }
    


    Key Points

    • Handles base 2 up to 36 (CAVEAT: you'll have to ensure your base is correct since there is no exception handling.
    • Recursion method is only 3 lines long! (code golf style)

    Analysis

    The following is the runtime analysis of both methods compared to the standard ToString() on my computer.

    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
    

    The results indicate the iteration and recursion methods run 5.49 and 5.00 times slower than the standard ToString() method.

    And here is the code I used for the analysis:

    class Program
    {
        static void Main(string[] args)
        {
            var r = new Random();
            var sw = new System.Diagnostics.Stopwatch();
    
            var loop = new List<long>();
            var recr = new List<long>();
            var std = new List<long>();
            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();
        }
    
    0 讨论(0)
  • 2020-12-12 14:11

    Recursion:

        public static string integerToString(int integerPassedIn)
        {
            ICollection<char> res = new List<char>();
            IntToStringRecusion(integerPassedIn, res);
            if (integerPassedIn < 0) res.Add('-');
            return new string(res.Reverse().ToArray()).PadLeft(1,'0');
        }
    
        static void IntToStringRecusion(int integerPassedIn, ICollection<char> array)
        {
            if (integerPassedIn == 0) return;
            array.Add((char)(48 + Math.Abs(integerPassedIn % 10)));
            IntToStringRecusion(integerPassedIn / 10, array);
        }
    
    0 讨论(0)
  • 2020-12-12 14:13

    you can convert any digit to a char like this

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

    The magic number 48 is the ASCII value of the char 0 and they are sequential in the ASCII table thus you can just add the digit to get the corresponding value in the ASCII table. and you can get the digits in the integer iteratively using the modulus operator % Borrowing the general structure from pswg you would get

    public string IntToString(int a) {
      var str = string.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
    }
    
    0 讨论(0)
  • 2020-12-12 14:14

    easy peasy:

    string s = 5 + ""
    //s = "5"
    
    0 讨论(0)
  • 2020-12-12 14:18
        public static string integerToString(int integerPassedIn)
        {
            if (integerPassedIn == 0) return "0";
            var negative = integerPassedIn < 0;
            var res = new List<char>();
            while(integerPassedIn != 0)
            {
               res.Add((char)(48 + Math.Abs(integerPassedIn % 10)));
               integerPassedIn /= 10;
            }
            res.Reverse();
            if (negative) res.Insert(0, '-');
            return new string(res.ToArray());
        }
    
    0 讨论(0)
  • 2020-12-12 14:22

    Something like this:

    public string IntToString(int a)
    {    
        var chars = new[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
        var str = string.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;
    }
    

    Update: Here's another version which is shorter and should perform much better, since it eliminates all string concatenation in favor of manipulating a fixed-length array. It supports bases up to 16, but it would be easy to extend it to higher bases. It could probably be improved further:

    public string IntToString(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);
    }
    
    0 讨论(0)
提交回复
热议问题