В.NET, что лучший способ состоит в том, чтобы найти длиной целого числа в символах, если бы это было представлено как строка?
например.
1 = 1 символ
10 = 2 символа
99 = 2 символа
100 = 3 символа
1000 = 4 символа
Очевидный ответ должен преобразовать интервал в строку и получить ее длину, но я хочу лучшую производительность, возможную без издержек создания новой строки.
вы можете использовать логарифмы для вычисления длины int:
public static int IntLength(int i) {
if (i <= 0) throw new ArgumentOutOfRangeException();
return (int)Math.Floor(Math.Log10(i)) + 1;
}
тест проходит:
[Test]
public void TestIntLength() {
Assert.AreEqual(1, IntLength(1));
Assert.AreEqual(1, IntLength(9));
Assert.AreEqual(2, IntLength(10));
Assert.AreEqual(2, IntLength(99));
Assert.AreEqual(3, IntLength(100));
Assert.AreEqual(3, IntLength(999));
Assert.AreEqual(4, IntLength(1000));
Assert.AreEqual(10, IntLength(int.MaxValue));
}
быстрый тест показал, что log-метод в 4 раза быстрее, чем метод int.ToString (). Length. .
метод, показанный GvS ниже (с использованием if-операторов), еще в 6 раз (!) Быстрее, чем метод журнала:
public static int IntLengthIf(int i) {
if (i < 10) return 1;
if (i < 100) return 2;
if (i < 1000) return 3;
if (i < 10000) return 4;
if (i < 100000) return 5;
if (i < 1000000) return 6;
if (i < 10000000) return 7;
if (i < 100000000) return 8;
if (i < 1000000000) return 9;
throw new ArgumentOutOfRangeException();
}
вот точное время для чисел от 1 до 10000000:
IntLengthToString: 4205ms
IntLengthLog10: 1122ms
IntLengthIf: 201ms
Если вам нужно иметь дело с отрицательными числами, вы можете взять решение stmax со спином:
public static int IntLength(int i) {
if (i == 0) return 1; // no log10(0)
int n = (i < 0) ? 2 : 1;
i = (i < 0) ? -i : i;
return (int)Math.Floor(Math.Log10(i)) + n;
}
Если ввод находится в диапазоне 0-10000
if (i < 10) return 1;
if (i < 100) return 2;
if (i < 1000) return 3;
if (i < 10000) return 4;
// etc
Если вы хотите сделать это математически, вы можете попробовать следующее:
int integer = 100
int charCount = (int) Math.Ceiling(Math.Log10(integer+1));
Я сомневаюсь, что это намного быстрее, чем преобразование в строку, хотя
Вы можете использовать что-то вроде этого:
int integer = 100;
int charachtersCount = 0;
while (integer > 0)
{
integer = integer/10;
charachtersCount++;
}
Но действительно ли вам нужно это оптимизировать? На самом деле я бы предпочел использовать строку (выглядит намного лучше):
integer.ToString().Length
Вы можете сделать:
int ndig = 1;
if (n < 0){n = -n; ndig++;}
if (n >= 100000000){n /= 100000000; ndig += 8;}
if (n >= 10000){n /= 10000; ndig += 4;}
if (n >= 100){n /= 100; ndig += 2;}
if (n >= 10){n /= 10; ndig += 1;}
или что-то в этом роде. Требуется 4 сравнения и 0-4 деления.
(В 64-битных версиях необходимо добавить пятый уровень.)