1. введение
В этом кратком руководстве мы рассмотрим различные способы получения количества цифр в целочисленном в Java.
Мы также проанализируем эти различные методы и выясним, какой алгоритм лучше всего подходит для нашей ситуации.
Дальнейшее чтение:
Как округлить число до N десятичных знаков в Java
Проверьте, является ли строка Числовой в Java
Практическое руководство по десятичному формату
2. Количество цифр в целочисленном числе
Для методов, обсуждаемых здесь, мы рассматриваем только положительные целые числа. Если мы ожидаем каких-либо отрицательных входных данных, то мы можем сначала использовать Math.abs(число) перед использованием любого из этих методов.
2.1. Решение На основе строк
Возможно , самый простой способ получить количество цифр в Integer – это преобразовать его в String и вызвать метод length () . Это вернет длину Строки представления нашего числа:
int length = String.valueOf(number).length();
Но это может быть неоптимальным подходом, так как этот оператор включает выделение памяти для строки для каждой оценки . JVM должен сначала проанализировать наш номер и скопировать его цифры в отдельную Строку , А также выполнить ряд различных операций (например, сохранение временных копий, обработка преобразований Юникода и т. Д.).
Если у нас есть только несколько чисел для оценки, то мы можем явно пойти с этим решением – потому что разница между этим и любым другим подходом будет пренебрегаться даже для больших чисел.
2.2. Логарифмический Подход
Для чисел, представленных в десятичной форме, если мы возьмем их логин в базе 10 и округлим его, то получим количество цифр в этом числе:
int length = (int) (Math.log10(number) + 1);
Обратите внимание, что log 10 0 какого-либо числа не определено. Итак, если мы ожидаем каких-либо входных данных со значением 0 , тогда мы можем проверить и это.
Логарифмический подход значительно быстрее, чем подход на основе String , поскольку ему не нужно проходить процесс преобразования данных. Это просто включает в себя простой, простой расчет без какой-либо дополнительной инициализации объекта или циклов.
2.3. Повторное Умножение
В этом методе мы возьмем временную переменную (инициализированную в 1) и будем непрерывно умножать ее на 10, пока она не станет больше нашего числа. Во время этого процесса мы также будем использовать переменную length , которая будет отслеживать длину числа:
int length = 0; long temp = 1; while (temp <= number) { length++; temp *= 10; } return length;
В этом коде строка temp совпадает с записью temp = (temp << 3) + (temp << 1) . Поскольку умножение обычно является более дорогостоящей операцией на некоторых процессорах по сравнению с операторами сдвига, последние могут быть немного более эффективными.
2.4. Деление на две степени
Если мы знаем о диапазоне нашего числа, то мы можем использовать вариацию, которая еще больше сократит наши сравнения. Этот метод делит число на степени двух (например, 1, 2, 4, 8 и т. Д.):
Этот метод делит число на степени двух (например, 1, 2, 4, 8 и т. Д.):
int length = 1; if (number >= 100000000) { length += 8; number /= 100000000; } if (number >= 10000) { length += 4; number /= 10000; } if (number >= 100) { length += 2; number /= 100; } if (number >= 10) { length += 1; } return length;
Он использует тот факт, что любое число может быть представлено сложением степеней 2. Например, 15 можно представить в виде 8+4+2+1, которые все являются степенями 2.
Для 15-значного числа мы бы провели 15 сравнений в нашем предыдущем подходе, который мы сократили до 4 в этом методе.
2.5. Разделяй и властвуй
Это, возможно, самый громоздкий подход по сравнению со всеми другими, описанными здесь, но излишне говорить, этот самый быстрый , потому что мы не выполняем никакого типа преобразования, умножения, сложения или инициализации объекта.
Мы получаем наш ответ всего в трех или четырех простых утверждениях if :
if (number < 100000) { if (number < 100) { if (number < 10) { return 1; } else { return 2; } } else { if (number < 1000) { return 3; } else { if (number < 10000) { return 4; } else { return 5; } } } } else { if (number < 10000000) { if (number < 1000000) { return 6; } else { return 7; } } else { if (number < 100000000) { return 8; } else { if (number < 1000000000) { return 9; } else { return 10; } } } }
Подобно предыдущему подходу, мы можем использовать этот метод только в том случае, если мы знаем о диапазоне нашего числа.
3. Бенчмаркинг
Теперь, когда у нас есть хорошее понимание потенциальных решений, давайте проведем простой бенчмаркинг всех наших методов с использованием жгута Java Microbenchmark (JMH) .
В следующей таблице показано среднее время обработки каждой операции (в наносекундах):
Benchmark Mode Cnt Score Error Units Benchmarking.stringBasedSolution avgt 200 32.736 ± 0.589 ns/op Benchmarking.logarithmicApproach avgt 200 26.123 ± 0.064 ns/op Benchmarking.repeatedMultiplication avgt 200 7.494 ± 0.207 ns/op Benchmarking.dividingWithPowersOf2 avgt 200 1.264 ± 0.030 ns/op Benchmarking.divideAndConquer avgt 200 0.956 ± 0.011 ns/op
Решение на основе String , которое является самым простым, также является самой дорогостоящей операцией, поскольку это единственная операция, которая требует преобразования данных и инициализации новых объектов.
Логарифмический подход значительно более эффективен по сравнению с предыдущим решением, поскольку он не требует преобразования данных. И, будучи однострочным решением, это может быть хорошей альтернативой подходу на основе String – .
Повторное умножение включает в себя простое умножение, пропорциональное длине числа; например, если число состоит из пятнадцати цифр, то этот метод будет включать в себя пятнадцать умножений.
Однако самый следующий метод использует тот факт, что каждое число может быть представлено степенями двух (подход, аналогичный BCD), и сводит то же самое к 4 операциям деления, поэтому он еще более эффективен, чем первый.
Наконец, как мы можем заключить, наиболее эффективным алгоритмом является многословная реализация “Разделяй и властвуй” , которая дает ответ всего в трех или четырех простых операторах if. Мы можем использовать его, если у нас есть большой набор данных чисел, которые нам нужно проанализировать.
4. Заключение
В этой краткой статье мы описали некоторые из способов найти количество цифр в целочисленном и сравнили эффективность каждого подхода.
И, как всегда, вы можете найти полный код на GitHub .