Fastest way to separate the digits of an int into an array in .NET?

后端 未结 11 789
天涯浪人
天涯浪人 2021-01-31 20:07

I want to separate the digits of an integer, say 12345, into an array of bytes {1,2,3,4,5}, but I want the most performance effective way to do that, because my program does tha

11条回答
  •  南方客
    南方客 (楼主)
    2021-01-31 20:59

    divide and mod tend to be slow operations. I wanted to find out if a solution using multiply and subtraction would be faster and it seems to be (on my computer):

        public static void ConvertToArrayOfDigits2(int value, int[] digits)
        {
            double v = value;
            double vby10 = v * .1;
    
            for (int index = digits.Length - 1; index >= 0; index--)
            {
                int ivby10 = (int)vby10;
                digits[index] = (int)(v)- ivby10* 10;
                v = ivby10;
                vby10 = ivby10 * .1;
            }       
        }
    

    I am passing in an array instead of allocating it every time to take the memory allocator and length out of the equation. This version will produce leading zeros if the array is longer than the number. Compared to a similarly converted version of Jon's example:

        public static void ConvertToArrayOfDigits(int value, int[] digits){
    
            for (int index = digits.Length - 1; index >= 0; index--)    { 
                digits[index] = value % 10;    
                value = value / 10;  
            }   
        }
    

    the no divide/mod version took about 50 more time to generate all the arrays up to a given number. I also tried using floats and it was only about 5-10% slower (the double version was quicker than the float version).

    Just because it was bothering me, here is an unrolled version which is just slightly faster again:

            public static void ConvertToArrayOfDigits3(int value, int[] digits)
        {
            double v = value;
            double vby10 = v * .1;
            int ivby10;
    
            switch(digits.Length -1){
                default:
                    throw new ArgumentOutOfRangeException();
                case 10:
                    ivby10 = (int)vby10;
                    digits[10] = (int)(v) - ivby10 * 10;
                    v = ivby10;
                    vby10 = ivby10 * .1;
                    goto case 9;
                case 9:
                    ivby10 = (int)vby10;
                    digits[9] = (int)(v) - ivby10 * 10;
                    v = ivby10;
                    vby10 = ivby10 * .1;
                    goto case 8;
                case 8:
                    ivby10 = (int)vby10;
                    digits[8] = (int)(v) - ivby10 * 10;
                    v = ivby10;
                    vby10 = ivby10 * .1;
                    goto case 7;
                case 7:
                    ivby10 = (int)vby10;
                    digits[7] = (int)(v) - ivby10 * 10;
                    v = ivby10;
                    vby10 = ivby10 * .1;
                    goto case 6;
                case 6:
                    ivby10 = (int)vby10;
                    digits[6] = (int)(v) - ivby10 * 10;
                    v = ivby10;
                    vby10 = ivby10 * .1;
                    goto case 5;
                case 5:
                    ivby10 = (int)vby10;
                    digits[5] = (int)(v) - ivby10 * 10;
                    v = ivby10;
                    vby10 = ivby10 * .1;
                    goto case 4;
                case 4:
                    ivby10 = (int)vby10;
                    digits[4] = (int)(v) - ivby10 * 10;
                    v = ivby10;
                    vby10 = ivby10 * .1;
                    goto case 3;
                case 3:
                    ivby10 = (int)vby10;
                    digits[3] = (int)(v) - ivby10 * 10;
                    v = ivby10;
                    vby10 = ivby10 * .1;
                    goto case 2;
                case 2:
                    ivby10 = (int)vby10;
                    digits[2] = (int)(v) - ivby10 * 10;
                    v = ivby10;
                    vby10 = ivby10 * .1;
                    goto case 1;
                case 1:
                    ivby10 = (int)vby10;
                    digits[1] = (int)(v) - ivby10 * 10;
                    v = ivby10;
                    vby10 = ivby10 * .1;
                    goto case 0;
                case 0:
                    ivby10 = (int)vby10;
                    digits[0] = (int)(v) - ivby10 * 10;
                    break;
            }
    
        }
    

提交回复
热议问题