IT story

ToString ()을 사용하지 않고 C #에서 Int를 String으로 어떻게 변환합니까?

hot-time 2020. 12. 29. 07:53
반응형

ToString ()을 사용하지 않고 C #에서 Int를 String으로 어떻게 변환합니까?


기본 toString 기능을 사용하지 않고 다음 int 인수를 문자열로 변환합니다.

public string integerToString(int integerPassedIn){    
    //Your code here
}

모든 것을 상속 이후 ObjectObjectToString()당신이 변환 얼마나 방법 intA를 string네이티브 사용하지 않고 ToString()방법을?

문자열 연결의 문제점은 ToString()하나에 도달하거나 Object클래스에 도달 할 때까지 체인 을 호출한다는 것입니다 .

사용하지 않고 C #에서 정수를 문자열로 어떻게 변환 ToString()합니까?


이 같은:

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;
}

업데이트 : 고정 길이 배열을 조작하기 위해 모든 문자열 연결을 제거하기 때문에 더 짧고 훨씬 더 나은 성능을 발휘해야하는 또 다른 버전이 있습니다. 최대 16 개의베이스를 지원하지만 더 높은베이스로 확장하기 쉽습니다. 더 개선 될 수 있습니다.

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);
}

이것이 내가 항상 사용하는 솔루션입니다.

    public static string numberBaseChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    public static string IntToStringWithBase(int n, int b) {
        return IntToStringWithBase(n, b, 1);
    }

    public static string IntToStringWithBase(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;
    }

이것은 매우 복잡해 보이지만 다음과 같은 기능이 있습니다.

  • 기수 2 ~ 36 지원
  • 음수 값 처리
  • 선택적 총 자릿수

나는 연결 operator +호출을 진정으로 확신하지 ToString못하지만 그것이 사실이라면 다음과 같은 작업을 수행하여 두 가지를 피할 수 있습니다.

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<char> l = new List<char>();
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 String(l.ToArray());

정수는 최하위 숫자부터 최상위까지 처리됩니다. 모듈로 10 (% 10)을 사용하여 단일 숫자를 계산 한 다음 문자 값 '0'에 추가합니다. 결과적으로 '0', '1', ..., '9'문자 중 하나가됩니다.

숫자는 처리 될 때 역순으로 표시되어야하므로 스택으로 푸시됩니다 (최상위 숫자에서 최하위 숫자). 문자열 앞에 숫자를 반복적으로 붙이는 대신 이렇게하는 것이 더 효율적일 수 있지만, 숫자 수가 매우 적기 때문에 확실하게 벤치 마크를 수행해야합니다.

양수가 아닌 숫자를 처리하려면 추가 처리가 필요합니다.

public string IntToString(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<char>();
  while (a != 0) {
    var c = a%10 + '0';
    stack.Push((char) c);
    a /= 10;
  }
  if (isNegative)
    stack.Push('-');
  return new string(stack.ToArray());
}

내 첫 번째 버전 StringBuilder에서는 문자 배열에서 문자열을 만드는 데 a 를 사용했지만 "out of the"문자열을 얻으려면 StringBuilder라는 메서드를 호출해야합니다 ToString. 분명히이 방법은이 질문이 무엇인지에 대한 문자열 변환을 int로 수행하지 않습니다.

그러나 호출하지 않고 문자열을 만들 수 있음을 증명하기 위해 생성자 ToString를 사용하는 것으로 전환 string했습니다 StringBuilder.

그리고 ToString어떤 형태로든 금지 된 경우 문서에 표시된대로 문자열 연결을 사용할 수 없습니다 string.Concat.

이 메서드는 arg0 및 arg1의 매개 변수가없는 ToString 메서드를 호출하여 arg0과 arg1을 연결합니다. 구분 기호를 추가하지 않습니다.

그래서 실행 s += '1'하면 '1'.ToString(). 그러나 나에게 이것은 중요하지 않습니다. 중요한 부분은 int를 문자열로 변환하는 방법입니다.


더 짧은 버전과 다음을 사용하는 버전을 목표로합니다 Math.DivRem.

string IntToString(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;
}

new string(..., 1)생성자 의 사용은 ToString아무것도 호출되지 않는 OP의 요구 사항을 충족시키는 방법 일뿐 입니다.


여기에 런타임 분석과 함께 반복 및 재귀를 사용하는 방법이 있습니다.

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];
    }
}


키 포인트

  • 기본 2를 최대 36까지 처리합니다 (주의 : 예외 처리가 없으므로 기본이 올바른지 확인해야합니다.
  • 재귀 방법은 단 3 줄입니다! (코드 골프 스타일)

분석

다음은 ToString()내 컴퓨터 의 표준과 비교 한 두 방법의 런타임 분석입니다 .

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

결과는 반복 및 재귀 방법이 표준 ToString()방법 보다 5.49 배 및 5.00 배 느리게 실행됨을 나타냅니다 .

분석에 사용한 코드는 다음과 같습니다.

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();
    }

다음과 같이 모든 숫자를 문자로 변환 할 수 있습니다.

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

매직 번호 48는 문자의 ASCII 값이며 0ASCII 테이블에서 순차적이므로 숫자를 추가하여 ASCII 테이블에서 해당 값을 가져올 수 있습니다. 모듈러스 연산자를 사용하여 정수의 숫자를 반복적 %으로 얻을 수 있습니다. pswg에서 일반 구조를 빌리면 얻을 수 있습니다.

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
}

    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());
    }

재귀 :

    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);
    }

이것이 C ++ 인 경우 :

public string IntToString(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);
}

참조 URL : https://stackoverflow.com/questions/17575375/how-do-i-convert-an-int-to-a-string-in-c-sharp-without-using-tostring

반응형