Рубрики
Без рубрики

Количество цифр в целом в Java

Изучите различные способы получения количества цифр в целом в Java.

Автор оригинала: baeldung.

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 .