Вычисление количества символов в переменной (C#)

Какой из вариантов вычисления количества символов в числе эффективнее.

через перебор

for(ulong t = degre_of; t > 0; t = t / 10)
{
    deg_lenght++;
}

или через длину строки

deg_lenght = degre_of.ToString().Length;

Ответы (1 шт):

Автор решения: aepot

Зачем гадать, давайте протестируем.

Ставим Benchmark.NET, пишем вот такой тест. Так же добавлю метод с логарифмом, который предложил @demonplus в комментариях.

class Program
{
    static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<MyBenchmark>();
        Console.ReadKey();
    }
}

[MemoryDiagnoser]
public class MyBenchmark
{
    [Benchmark]
    public int MathTest()
    {
        int total = 0;
        for (uint number = 1; number <= 10000000; number++)
        {
            int length = 0;
            for (uint t = number; t > 0; t /= 10)
            {
                length++;
            }
            total += length;
        }
        return total;
    }

    [Benchmark]
    public int StringTest()
    {
        int total = 0;
        for (uint number = 1; number <= 10000000; number++)
        {
            total += number.ToString().Length;
        }
        return total;
    }

    [Benchmark]
    public int Log10Test()
    {
        int total = 0;
        for (uint number = 1; number <= 10000000; number++)
        {
            total += (int)Math.Log10(number) + 1;
        }
        return total;
    }
}

Считаем сумму длин всех чисел от 1 до миллиона. Если вывести в консоль, результат всех методов будет одинаковый.

Console.WriteLine(MathTest());
Console.WriteLine(StringTest());
Console.WriteLine(Log10Test());
68888897
68888897
68888897

Запускаем тест производительности

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042
Intel Core i7-4700HQ CPU 2.40GHz (Haswell), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=5.0.103
  [Host]     : .NET Core 3.1.12 (CoreCLR 4.700.21.6504, CoreFX 4.700.21.6905), X64 RyuJIT
  DefaultJob : .NET Core 3.1.12 (CoreCLR 4.700.21.6504, CoreFX 4.700.21.6905), X64 RyuJIT


|     Method |      Mean |    Error |   StdDev |       Gen 0 | Gen 1 | Gen 2 |   Allocated |
|----------- |----------:|---------:|---------:|------------:|------:|------:|------------:|
|   MathTest |  57.64 ms | 0.391 ms | 0.347 ms |           - |     - |     - |       528 B |
| StringTest | 356.61 ms | 3.732 ms | 3.309 ms | 127000.0000 |     - |     - | 399199720 B |
|  Log10Test |  87.39 ms | 0.628 ms | 0.524 ms |           - |     - |     - |        95 B |

И видим, что метод с использованием строки не только в 7 раз медленнее, чем метод с циклом, но еще и скушал дополнительно 400 кб памяти для работы. И цикл все-таки оказался быстрее десятичного логарифма.

Кстати, в методе с циклом есть баг, который я просто обошел в тестах, если число равно 0, то метод со строкой вернет 1, а метод с циклом - 0. Но вы уже наверняка поняли, как это исправить.

→ Ссылка