Спосіб отримання кількості цифр в int?


385

Чи існує більш охайний спосіб отримати довжину int, ніж цей метод?

int length = String.valueOf(1000).length();

7
визначте довжину int будь ласка.
Том

24
Я думаю, що він хоче порахувати цифри в кількості.
Альберто Закканні

3
Відповіді, які люди дають вам, є правильними ... вони дають вам довжину int, не перетворюючи її на рядок ... але чому ви не хочете перетворити її на рядок? Це швидкість? Якщо так, я не впевнений, що ці методи будуть швидшими ... ви можете зробити тести (або вирішити, чи це навіть має значення.)
Беска,

3
Шістнадцяткові цифри @ptomli - це все ще цифри, лише в іншій базовій системі.
Марк Пім

2
@Ptomli Зрозуміло, але як у функції Integer.toString, так і в загальній розмові десятковою є типова цифра. Коли банк каже мені: "Запишіть суму цього чека в це поле", я не запитую їх, чи слід писати це у десятковій, шістнадцятковій або восьмеричній формі. Ми припускаємо десяткову форму, якщо інше не вказано або не вимагається контекстом.
Джей

Відповіді:


349

Ваше рішення на основі рядків - це цілком нормально, в цьому немає нічого "непоганого". Ви повинні усвідомити, що математично цифри не мають довжини, а також не мають цифр. Довжина та цифри - це властивості фізичного зображення числа в певній основі, тобто рядку.

Рішення, засноване на логарифмі, робить (деякі) ті ж речі, що і на основі рядків, робить це всередині, і, ймовірно, робить це (незначно) швидше, оскільки воно лише створює довжину і ігнорує цифри. Але я б насправді не вважав це більш зрозумілим у намірі - і це найважливіший фактор.


54
+1 для врахування наміру коду під час вибору способу вирішення проблеми
pupeno

5
Точка даних: На моїй машині метод журналу, здається, працює трохи менше, ніж удвічі швидше, ніж методи довжини рядків. Я б не назвав це несуттєвим, якщо метод називається багато або в критичному для часу розділі коду.
CPerkins

1
Дивіться моє тестування базового одиниці нижче (яке може бути і хибним, я не є експертом із орієнтиру). За великої кількості пробіжок (100 000 000) на моїй машині швидкість становить від 11 до 8 секунд навряд чи вдвічі швидша.
Жан

5
@CPerkins. Передчасна оптимізація. Ви знаєте шпіль.
Майкл Боргвардт

11
Деякі (досить пізні) доповнення: це може не працювати належним чином для від'ємних значень, залежно від того, ви очікуєте, що "-" буде цифрою чи ні. Додавання Math.abs()виправить це, однак.
YingYang

265

Логарифм - ваш друг:

int n = 1000;
int length = (int)(Math.log10(n)+1);

Примітка: діє лише для n> 0.


2
І це швидше чи краще, ніж використовувати мій варіант?
fnst

+1 Ти побив мене на секунду, і твоя відповідь була правильною, де моя трохи збилася. Однак зауважте, що компілятор поскаржиться на відсутність ролі до int
Дірк

2
@Tom Чому ти вважаєш, що це дорого? Можна припустити, що математичний співпроцесор виконає його, тому він може бути близький до швидкості додавання. Навіть якщо java зараз не використовує спільний процесор, це хороше припущення, що це може бути… (Ми просто ігноруємо ваші ще більш неосвічені наслідки того, що Java повільна, тому що вас, мабуть, не цікавлять докази - або якби ти був, ти пішов би на shootout.alioth.debian.org і дізнайся для себе)
Білл К

8
Працює ... якщо тільки значення, яке ви перевіряєте, = 0, що дасть незвичайні результати (-2147483647). API Math.log10: "Якщо аргумент позитивний нуль або мінус нуль, то результат - негативна нескінченність."
mujimu

2
+1 Представлення методу, який не передбачає розподілу об'єктної пам'яті, що є необхідним для максимального використання, щоб уникнути колекцій GC.
Майкл Войцік

158

Найшвидший підхід: діліться і перемагайте.

Якщо припустити, що ваш діапазон становить від 0 до MAX_INT, то у вас є від 1 до 10 цифр. Ви можете наблизитись до цього інтервалу, використовуючи ділення та підкорити, маючи до 4 порівнянь на кожен вхід. Спочатку ви поділяєте [1..10] на [1..5] та [6..10] одним порівнянням, а потім кожен інтервал довжини 5, який ви поділяєте, використовуючи одне порівняння на одну довжину 3 та одну інтервал довжини 2. Інтервал довжини 2 вимагає ще одного порівняння (всього 3 порівняння), інтервал довжини 3 можна розділити на інтервал довжини 1 (розчин) та інтервал довжини 2. Отже, вам потрібно 3 або 4 порівняння.

Ні поділів, ні операцій з плаваючою комою, ні дорогих логарифмів, лише цілі порівняння.

Код (довгий, але швидкий):

if (n < 100000){
        // 5 or less
        if (n < 100){
            // 1 or 2
            if (n < 10)
                return 1;
            else
                return 2;
        }else{
            // 3 or 4 or 5
            if (n < 1000)
                return 3;
            else{
                // 4 or 5
                if (n < 10000)
                    return 4;
                else
                    return 5;
            }
        }
    } else {
        // 6 or more
        if (n < 10000000) {
            // 6 or 7
            if (n < 1000000)
                return 6;
            else
                return 7;
        } else {
            // 8 to 10
            if (n < 100000000)
                return 8;
            else {
                // 9 or 10
                if (n < 1000000000)
                    return 9;
                else
                    return 10;
            }
        }
    }

Бенчмарк (після розминки JVM) - див. Код нижче, щоб побачити, як виконується тест:

  1. базовий метод (з String.length): 2145 мс
  2. метод log10: 711 мс = 3,02 рази швидший за базовий рівень
  3. повторне ділення: 2797 мс = 0,77 рази швидше, ніж вихідне
  4. діліться і перемагай: 74 мс = 28,99
    рази швидше, ніж базовий

Повний код:

public static void main(String[] args)
throws Exception
{

    // validate methods:
    for (int i = 0; i < 1000; i++)
        if (method1(i) != method2(i))
            System.out.println(i);
    for (int i = 0; i < 1000; i++)
        if (method1(i) != method3(i))
            System.out.println(i + " " + method1(i) + " " + method3(i));
    for (int i = 333; i < 2000000000; i += 1000)
        if (method1(i) != method3(i))
            System.out.println(i + " " + method1(i) + " " + method3(i));
    for (int i = 0; i < 1000; i++)
        if (method1(i) != method4(i))
            System.out.println(i + " " + method1(i) + " " + method4(i));
    for (int i = 333; i < 2000000000; i += 1000)
        if (method1(i) != method4(i))
            System.out.println(i + " " + method1(i) + " " + method4(i));

    // work-up the JVM - make sure everything will be run in hot-spot mode
    allMethod1();
    allMethod2();
    allMethod3();
    allMethod4();

    // run benchmark
    Chronometer c;

    c = new Chronometer(true);
    allMethod1();
    c.stop();
    long baseline = c.getValue();
    System.out.println(c);

    c = new Chronometer(true);
    allMethod2();
    c.stop();
    System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");

    c = new Chronometer(true);
    allMethod3();
    c.stop();
    System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");

    c = new Chronometer(true);
    allMethod4();
    c.stop();
    System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");
}


private static int method1(int n)
{
    return Integer.toString(n).length();
}
private static int method2(int n)
{
    if (n == 0)
        return 1;
    return (int)(Math.log10(n) + 1);
}
private static int method3(int n)
{
    if (n == 0)
        return 1;
    int l;
    for (l = 0 ; n > 0 ;++l)
        n /= 10;
    return l;
}
private static int method4(int n)
{
    if (n < 100000)
    {
        // 5 or less
        if (n < 100)
        {
            // 1 or 2
            if (n < 10)
                return 1;
            else
                return 2;
        }
        else
        {
            // 3 or 4 or 5
            if (n < 1000)
                return 3;
            else
            {
                // 4 or 5
                if (n < 10000)
                    return 4;
                else
                    return 5;
            }
        }
    }
    else
    {
        // 6 or more
        if (n < 10000000)
        {
            // 6 or 7
            if (n < 1000000)
                return 6;
            else
                return 7;
        }
        else
        {
            // 8 to 10
            if (n < 100000000)
                return 8;
            else
            {
                // 9 or 10
                if (n < 1000000000)
                    return 9;
                else
                    return 10;
            }
        }
    }
}


private static int allMethod1()
{
    int x = 0;
    for (int i = 0; i < 1000; i++)
        x = method1(i);
    for (int i = 1000; i < 100000; i += 10)
        x = method1(i);
    for (int i = 100000; i < 1000000; i += 100)
        x = method1(i);
    for (int i = 1000000; i < 2000000000; i += 200)
        x = method1(i);

    return x;
}
private static int allMethod2()
{
    int x = 0;
    for (int i = 0; i < 1000; i++)
        x = method2(i);
    for (int i = 1000; i < 100000; i += 10)
        x = method2(i);
    for (int i = 100000; i < 1000000; i += 100)
        x = method2(i);
    for (int i = 1000000; i < 2000000000; i += 200)
        x = method2(i);

    return x;
}
private static int allMethod3()
{
    int x = 0;
    for (int i = 0; i < 1000; i++)
        x = method3(i);
    for (int i = 1000; i < 100000; i += 10)
        x = method3(i);
    for (int i = 100000; i < 1000000; i += 100)
        x = method3(i);
    for (int i = 1000000; i < 2000000000; i += 200)
        x = method3(i);

    return x;
}
private static int allMethod4()
{
    int x = 0;
    for (int i = 0; i < 1000; i++)
        x = method4(i);
    for (int i = 1000; i < 100000; i += 10)
        x = method4(i);
    for (int i = 100000; i < 1000000; i += 100)
        x = method4(i);
    for (int i = 1000000; i < 2000000000; i += 200)
        x = method4(i);

    return x;
}

Знову ж таки, орієнтир:

  1. базовий метод (з String.length): 2145 мс
  2. метод log10: 711 мс = 3,02 рази швидший за базовий рівень
  3. повторне ділення: 2797 мс = 0,77 рази швидше, ніж вихідне
  4. діліться і перемагай: 74 мс = 28,99
    рази швидше, ніж базовий

Редагувати: Після того, як я написав тест, я взяв пік проникнення в Integer.toString з Java 6, і я виявив, що він використовує:

final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                  99999999, 999999999, Integer.MAX_VALUE };

// Requires positive x
static int stringSize(int x) {
    for (int i=0; ; i++)
        if (x <= sizeTable[i])
            return i+1;
}

Я порівняв це з моїм рішенням "ділити і перемагай":

  1. ділитись і перемагай: 104 мс
  2. Рішення Java 6 - повторити та порівняти: 406ms

Моє скорочення майже в 4 рази швидше, ніж рішення Java 6.


7
це виглядає чудово. ви можете написати це трохи компактніше, використовуючи оператор?: для отримання більшого сприйняття
Андре Парей

88
поговоримо про передчасну оптимізацію: D
Гордон Густафсон

2
Мені це подобається! Як щодо блоку комутації замість так вкладених if-elseses?
Кебман

2
Я не усвідомлював усіх цих випадків, якщо б інакше операції були набагато швидшими, ніж перетворення int в String, а потім виклик .length. +1
Оген

15
Використовуючи термінальний оператор, він зводить його до 101 символу:n<100000?n<100?n<10?1:2:n<1000?3:n<10000?4:5:n<10000000?n<1000000?6:7:n<100000000?8:n<1000000000?9:10
Джонатан Гаврич

13

Два коментарі до вашого орієнтиру: Java - це складне середовище, що стосується простого вчасного збирання та збирання сміття тощо, щоб отримати справедливе порівняння, коли я запускаю тест, я завжди: (a) додаю два тести у циклі, який виконує їх у послідовності 5 або 10 разів. Досить часто тривалість другого проходу через цикл сильно відрізняється від першого. І (b) Після кожного "підходу" я роблю System.gc (), щоб спробувати викликати збирання сміття. В іншому випадку перший підхід може створити купу предметів, але недостатньо достатньо для збору сміття, тоді другий підхід створює кілька об’єктів, купа вичерпується, і збирання сміття працює. Тоді другий підхід "заряджається" за збирання сміття, залишеного першим підходом. Дуже несправедливо!

Однак, жодне з перерахованого вище не зробило суттєвої різниці в цьому прикладі.

З тими чи іншими модифікаціями я отримав зовсім інші результати, ніж ти. Коли я запустив це, так, то підхід toString давав час роботи від 6400 до 6600 мільйонів, тоді як підхід до журналу складає 20 000 - 20 400 міліс. Замість того, щоб трохи швидше, для мене підхід до журналу був у 3 рази повільнішим.

Зауважте, що два підходи пов'язані з дуже різними витратами, тому це не зовсім шокує: підхід toString створить безліч тимчасових об'єктів, які потрібно очистити, тоді як підхід до журналу потребує більш інтенсивних обчислень. Тож, можливо, різниця полягає в тому, що на машині з меншим обсягом пам'яті для ToString потрібно більше раундів збору сміття, тоді як на машині з більш повільним процесором додаткові обчислення журналу будуть більш болючими.

Я також спробував третій підхід. Я написав цю маленьку функцію:

static int numlength(int n)
{
    if (n == 0) return 1;
    int l;
    n=Math.abs(n);
    for (l=0;n>0;++l)
        n/=10;
    return l;           
}

Це було в 1600-1900 млн. - менше 1/3 підходу до StSring і 1/10 підходу до журналу на моїй машині.

Якщо у вас був широкий діапазон чисел, ви можете прискорити його далі, розпочавши ділення на 1000 або 1 000 000, щоб зменшити кількість разів через цикл. Я з цим не грав.


Ви спробували змінити вхід? Точка VM може оптимізувати цей графік інакше, що призведе до неправильних орієнтирів, оскільки він щоразу повертає ту саму попередньо обчислену річ.
Ерік

11

Використання Java

int nDigits = Math.floor(Math.log10(Math.abs(the_integer))) + 1;

використання import java.lang.Math.*;на початку

Використання C

int nDigits = floor(log10(abs(the_integer))) + 1;

використання inclue math.hна початку


1
Просто FYI, якщо the_integerце 0так , приведе до нескінченності , тому перевірте це.
Ерік Айгнер

9

Поки не можна залишити коментар, тому я опублікую окрему відповідь.

Рішення на основі логарифму не обчислює правильну кількість цифр для дуже великих довгих цілих чисел, наприклад:

long n = 99999999999999999L;

// correct answer: 17
int numberOfDigits = String.valueOf(n).length();

// incorrect answer: 18
int wrongNumberOfDigits = (int) (Math.log10(n) + 1); 

Рішення на основі логарифму обчислює неправильну кількість цифр у великих цілих числах


спробуйте (int) (Math.log10 (n + j)) замість того, де j 10 - (n - n / 10 * 10).
Ерік Стоун

8

Оскільки кількість цифр у базі 10 цілого числа становить лише 1 + усікання (log10 (число)) , ви можете зробити:

public class Test {

    public static void main(String[] args) {

        final int number = 1234;
        final int digits = 1 + (int)Math.floor(Math.log10(number));

        System.out.println(digits);
    }
}

Відредаговано тому, що в останньому редагуванні виправлено приклад коду, але не опис.


Класно. але я думаю, що йому потрібен abs (число), а також "0" - це також особливий випадок?
ДмитроК

Так. Якщо вам потрібно буде врахувати знак, вам доведеться зробити щось на зразок 1 + (int) Math.floor (Math.log10 (Math.abs (число))) + ((число <0)? 1: 0)
Дірк

5
Це Math.floorтрохи зайве, чи не так? Лиття на те, щоб intвсе-таки закруглити його.
CompuChip

5

Рішення Маріан адаптували для довгих чисел (до 9,223,372,036,854,775,807), якщо хтось захоче скопіювати та вставити його. У програмі я написав це, щоб цифри до 10000 були набагато більш імовірними, тому я зробив для них певну гілку. У будь-якому випадку це не суттєво зміниться.

public static int numberOfDigits (long n) {     
    // Guessing 4 digit numbers will be more probable.
    // They are set in the first branch.
    if (n < 10000L) { // from 1 to 4
        if (n < 100L) { // 1 or 2
            if (n < 10L) {
                return 1;
            } else {
                return 2;
            }
        } else { // 3 or 4
            if (n < 1000L) {
                return 3;
            } else {
                return 4;
            }
        }           
    } else  { // from 5 a 20 (albeit longs can't have more than 18 or 19)
        if (n < 1000000000000L) { // from 5 to 12
            if (n < 100000000L) { // from 5 to 8
                if (n < 1000000L) { // 5 or 6
                    if (n < 100000L) {
                        return 5;
                    } else {
                        return 6;
                    }
                } else { // 7 u 8
                    if (n < 10000000L) {
                        return 7;
                    } else {
                        return 8;
                    }
                }
            } else { // from 9 to 12
                if (n < 10000000000L) { // 9 or 10
                    if (n < 1000000000L) {
                        return 9;
                    } else {
                        return 10;
                    }
                } else { // 11 or 12
                    if (n < 100000000000L) {
                        return 11;
                    } else {
                        return 12;
                    }
                }
            }
        } else { // from 13 to ... (18 or 20)
            if (n < 10000000000000000L) { // from 13 to 16
                if (n < 100000000000000L) { // 13 or 14
                    if (n < 10000000000000L) { 
                        return 13;
                    } else {
                        return 14;
                    }
                } else { // 15 or 16
                    if (n < 1000000000000000L) {
                        return 15;
                    } else {
                        return 16;
                    }
                }
            } else { // from 17 to ...¿20?
                if (n < 1000000000000000000L) { // 17 or 18
                    if (n < 100000000000000000L) {
                        return 17;
                    } else {
                        return 18;
                    }
                } else { // 19? Can it be?
                    // 10000000000000000000L is'nt a valid long.
                    return 19;
                }
            }
        }
    }
}

Чи слід змінити назву цього питання на "Спосіб отримання кількості цифр в int / long?" (і додав тег "довгий")
JAIL

4

Ще один струнний підхід. Короткий і солодкий - для будь-якого цілого числа n.

int length = ("" + n).length();

Працює лише для натурального числа nта нуля. Можна використовувати ("" + Math.abs(n)).length()для отримання довжини від’ємного цілого числа.
ThisClark

3

Чи можна спробувати? ;)

на основі рішення Дірка

final int digits = number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));

3

Як щодо звичайної старої математики? Розділіть на 10, поки не досягнете 0.

public static int getSize(long number) {
        int count = 0;
        while (number > 0) {
            count += 1;
            number = (number / 10);
        }
        return count;
    }

1
Ви перевірили? Ви знаєте, що навіть якщо це важко для людської точки зору, це насправді не працює так само з "способом мислення" машини, правда? --- Дозвольте запропонувати одне: Створіть масив з двох мільйонів чисел, бажано Long.MAX_VALUE, що є найгіршим випадком складності вашого коду, і використовуйте System.nanoTime()для виконання пробного рішення щодо найгірших випадків складності іншого рішення. ++ Насправді, спробуйте його з масивом, заповненим рандомизатором, встановленим на діапазон 0до Long.MAX_VALUEзанадто, лише для тестування на "середню складність" ++ Ви можете знайти результати ... дуже шокуючі.
XenoRo

@thelima Це не працює правильно для нуля або негативів, але це незначна помилка. Принцип мені здається правильним. Який "шокуючий" результат ви маєте на увазі?
Джей

Скажімо, що комп'ютери ... Ну ... вони не люблять ділити. І в тих випадках, коли великі "черги" з великої кількості потрібно обробити, і кожна цифра в кожному обробленому номері потребуватиме поділу ... Ну ... Речі "починають дійсно повільно, дуже швидко" ... Якщо ви ловите мою сенс ... --- Ось чому ви бачите багато відповідей тут, використовуючи коди, засновані на тесті та порівнянні з кожною десятковою цифрою, використовуючи "if's, а не ділення: Якщо його не швидше, принаймні, він підтримує більшу частину своєї швидкості незалежно від з найгірших випадків --- Зробіть тест на використання розділів та логарифмів на великій кількості ...
XenoRo

@TheLima, про що ти говориш? Для int,цього цикл виконується максимум 11 разів. Чи є у вас якісь докази ваших тверджень?
Маркіз Лорн

@EJP З точки зору обладнання, поділ - це ітераційний процес. Найбільш швидкий алгоритм поділу, про який я знаю, - це radix4, який генерує 4 біти за ітерацію; тому для 32-бітового поділу потрібно як мінімум 8 ітерацій. Наприклад, множення можна зробити паралельно, а також розбити на більш прості множення; або до бітового рівня (вимагає всього 5 операцій), або з частковою розбиткою плюс оглядова таблиця в кінці (Класичний компроміс VS зі швидкістю). Справа не лише в тому, «скільки повторень»; проблема з підрозділами полягає в тому, "що кожна ітерація передбачає / робить на апаратному рівні"
XenoRo

2

Маріан Рішення, тепер із Тернарі:

 public int len(int n){
        return (n<100000)?((n<100)?((n<10)?1:2):(n<1000)?3:((n<10000)?4:5)):((n<10000000)?((n<1000000)?6:7):((n<100000000)?8:((n<1000000000)?9:10)));
    }

Бо ми можемо.


2
Це якось важко читати. Можливо, додайте пробіли та / або нові рядки.
michaelb958 - GoFundMonica

Але чорт це портативний!
Тревор Рудольф

1

Цікаво, я спробував це порівняти ...

import org.junit.Test;
import static org.junit.Assert.*;


public class TestStack1306727 {

    @Test
    public void bench(){
        int number=1000;
        int a= String.valueOf(number).length();
        int b= 1 + (int)Math.floor(Math.log10(number));

        assertEquals(a,b);
        int i=0;
        int s=0;
        long startTime = System.currentTimeMillis();
        for(i=0, s=0; i< 100000000; i++){
            a= String.valueOf(number).length();
            s+=a;
        }
        long stopTime = System.currentTimeMillis();
        long runTime = stopTime - startTime;
        System.out.println("Run time 1: " + runTime);
        System.out.println("s: "+s);
        startTime = System.currentTimeMillis();
        for(i=0,s=0; i< 100000000; i++){
            b= number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));
            s+=b;
        }
        stopTime = System.currentTimeMillis();
        runTime = stopTime - startTime;
        System.out.println("Run time 2: " + runTime);
        System.out.println("s: "+s);
        assertEquals(a,b);


    }
}

результати такі:

Час виконання 1: 6765
с: 400000000
Час виконання 2: 6000
с: 400000000

Тепер мені залишається цікаво, чи мій показник насправді щось означає, але я отримую послідовні результати (варіації в межах мс) протягом декількох циклів самого еталону ... :) Схоже, марно намагатися і оптимізувати це ...


редагувати: після коментаря ptomli, я замінив 'число' на 'i' у наведеному вище коді та отримав наступні результати протягом 5 пробіг лавки:

Час виконання 1: 11500
с: 788888890
Час виконання 2: 8547
с: 788888890

Час виконання 1: 11485
с: 788888890
Час виконання 2: 8547
с: 788888890

Час виконання 1: 11469
с: 788888890
Час виконання 2: 8547
с: 788888890

Час виконання 1: 11500
с: 788888890
Час виконання 2: 8547
с: 788888890

Час виконання 1: 11484
с: 788888890
Час виконання 2: 8547
с: 788888890

1
Тільки для задоволення, яка різниця в розподілі значень числа, наприклад, від 0 до трильйона? :)
ptomli

0

Що з цим рекурсивним методом?

    private static int length = 0;

    public static int length(int n) {
    length++;
    if((n / 10) < 10) {
        length++;
    } else {
        length(n / 10);
    }
    return length;
}

0

просте рішення:

public class long_length {
    long x,l=1,n;
    for (n=10;n<x;n*=10){
        if (x/n!=0){
            l++;
        }
    }
    System.out.print(l);
}

0

По-справжньому просте рішення:

public int numLength(int n) {
  for (int length = 1; n % Math.pow(10, length) != n; length++) {}
  return length;
}

Я б не назвав один рядок для циклу з порожнім тілом простим. Ні модуль потужністю 10, щоб побачити, якщо ви повернете те саме, що ви не можете використати для порівняння?
Teepeemm

0

Або замість довжини ви можете перевірити, чи число більше чи менше, ніж бажане число.

    public void createCard(int cardNumber, int cardStatus, int customerId) throws SQLException {
    if(cardDao.checkIfCardExists(cardNumber) == false) {
        if(cardDao.createCard(cardNumber, cardStatus, customerId) == true) {
            System.out.println("Card created successfully");
        } else {

        }
    } else {
        System.out.println("Card already exists, try with another Card Number");
        do {
            System.out.println("Enter your new Card Number: ");
            scan = new Scanner(System.in);
            int inputCardNumber = scan.nextInt();
            cardNumber = inputCardNumber;
        } while(cardNumber < 95000000);
        cardDao.createCard(cardNumber, cardStatus, customerId);
    }
}

}


Я не розумію. Схоже, ви відповідаєте на інше запитання.
Teepeemm

0

Я ще не бачив рішення на основі множення. Рішення на основі логарифмів, розділень та рядків стануть досить непростими щодо мільйонів тестових випадків, ось ось що для ints:

/**
 * Returns the number of digits needed to represents an {@code int} value in 
 * the given radix, disregarding any sign.
 */
public static int len(int n, int radix) {
    radixCheck(radix); 
    // if you want to establish some limitation other than radix > 2
    n = Math.abs(n);

    int len = 1;
    long min = radix - 1;

    while (n > min) {
        n -= min;
        min *= radix;
        len++;
    }

    return len;
}

У базі 10 це працює, тому що n по суті порівнюється з 9, 99, 999 ... так як min дорівнює 9, 90, 900 ... і n віднімається на 9, 90, 900 ...

На жаль, це не портативно, longпросто замінюючи кожен екземпляр intчерез переповнення. З іншого боку, це просто так буває, що він буде працювати для баз 2 і 10 (але погано не вдається для більшості інших баз). Вам знадобиться таблиця пошуку для точок переповнення (або тест поділу ... ew)

/**
 * For radices 2 &le r &le Character.MAX_VALUE (36)
 */
private static long[] overflowpt = {-1, -1, 4611686018427387904L,
    8105110306037952534L, 3458764513820540928L, 5960464477539062500L,
    3948651115268014080L, 3351275184499704042L, 8070450532247928832L,
    1200757082375992968L, 9000000000000000000L, 5054470284992937710L,
    2033726847845400576L, 7984999310198158092L, 2022385242251558912L,
    6130514465332031250L, 1080863910568919040L, 2694045224950414864L,
    6371827248895377408L, 756953702320627062L, 1556480000000000000L,
    3089447554782389220L, 5939011215544737792L, 482121737504447062L,
    839967991029301248L, 1430511474609375000L, 2385723916542054400L,
    3902460517721977146L, 6269893157408735232L, 341614273439763212L,
    513726300000000000L, 762254306892144930L, 1116892707587883008L,
    1617347408439258144L, 2316231840055068672L, 3282671350683593750L,
    4606759634479349760L};

public static int len(long n, int radix) {
    radixCheck(radix);
    n = abs(n);

    int len = 1;
    long min = radix - 1;
    while (n > min) {
        len++;
        if (min == overflowpt[radix]) break;
        n -= min;
        min *= radix;

    }

    return len;
}

0

З дизайном (на основі проблеми). Це альтернатива ділити-перемагай. Спочатку визначимо enum (враховуючи, що це лише для непідписаного int).

public enum IntegerLength {
    One((byte)1,10),
    Two((byte)2,100),
    Three((byte)3,1000),
    Four((byte)4,10000),
    Five((byte)5,100000),
    Six((byte)6,1000000),
    Seven((byte)7,10000000),
    Eight((byte)8,100000000),
    Nine((byte)9,1000000000);

    byte length;
    int value;

    IntegerLength(byte len,int value) {
        this.length = len;
        this.value = value;
    }

    public byte getLenght() {
        return length;
    }

    public int getValue() {
        return value;
    }
}

Тепер ми визначимо клас, який проходить через значення enum та порівняємо та повернемо відповідну довжину.

public class IntegerLenght {
    public static byte calculateIntLenght(int num) {    
        for(IntegerLength v : IntegerLength.values()) {
            if(num < v.getValue()){
                return v.getLenght();
            }
        }
        return 0;
    }
}

Час виконання цього рішення є таким же, як і підхід ділити і перемогти.


Розділення і перемога розпочнеться посередині і розділить зону пошуку, що залишилася. Це має лінійний час виконання. Але це не має значення лише для 9 порівнянь. Але це не зіпсується, якщо num>=Nine.getValue()?
Teepeemm

0

Хочеться це зробити здебільшого тому, що він / вона хоче "представити" це, що здебільшого означає, що його нарешті потрібно "в String-ed" (або трансформувати іншим способом) явно або неявно в будь-якому випадку; перед тим, як вона може бути представлена ​​(надрукована, наприклад).

Якщо це так, то просто спробуйте зробити необхідне "toString" явним і порахувати біти.


0

Ми можемо досягти цього за допомогою рекурсивної петлі

    public static int digitCount(int numberInput, int i) {
        while (numberInput > 0) {
        i++;
        numberInput = numberInput / 10;
        digitCount(numberInput, i);
        }
        return i;
    }

    public static void printString() {
        int numberInput = 1234567;
        int digitCount = digitCount(numberInput, 0);

        System.out.println("Count of digit in ["+numberInput+"] is ["+digitCount+"]");
    }

0

Я написав цю функцію, подивившись Integer.javaвихідний код.

private static int stringSize(int x) {
    final int[] sizeTable = {9, 99, 999, 9_999, 99_999, 999_999, 9_999_999,
            99_999_999, 999_999_999, Integer.MAX_VALUE};
    for (int i = 0; ; ++i) {
        if (x <= sizeTable[i]) {
            return i + 1;
        }
    }
}

0

Я бачу людей, які використовують бібліотеки String або навіть використовують клас Integer. Нічого поганого в цьому немає, але алгоритм отримання кількості цифр не такий складний. У цьому прикладі я використовую довгий, але він працює так само чудово з int.

 private static int getLength(long num) {

    int count = 1;

    while (num >= 10) {
        num = num / 10;
        count++;
    }

    return count;
}

0

немає String API, ні утиліти, ні перетворення типів, просто чиста ітерація Java ->

public static int getNumberOfDigits(int input) {
    int numOfDigits = 1;
    int base = 1;
    while (input >= base * 10) {
        base = base * 10;
        numOfDigits++;
    }
    return numOfDigits;
 }

Якщо хочете, ви можете довго шукати великих значень.


-1
    int num = 02300;
    int count = 0;
    while(num>0){
         if(num == 0) break;
         num=num/10;
         count++;
    }
    System.out.println(count);

Рішення "розділити на 10" було вперше опубліковано Синістом двома роками раніше.
Teepeemm

-1

Легкий рекурсивний спосіб

int    get_int_lenght(current_lenght, value)
{
 if (value / 10 < 10)
    return (current_lenght + 1);
return (get_int_lenght(current_lenght + 1, value))
}

не перевірений


3
Ви, ймовірно, повинні перевірити його тоді (і переконайтесь, що він дійсний на Java та правильно відформатований) Але рекурсивний підхід "розділити на 10" був опублікований Джедай Дулою 3 роки тому.
Teepeemm

-2

Ви можете ввести цифри, використовуючи послідовний поділ на десять:

int a=0;

if (no < 0) {
    no = -no;
} else if (no == 0) {
    no = 1;
}

while (no > 0) {
    no = no / 10;
    a++;
}

System.out.println("Number of digits in given number is: "+a);

Підхід "поділити на 10" вперше опублікував Синіста 3 роки тому. Це єдина причина, по якій я можу подумати про те, що ти отримав протизаконну заяву.
Teepeemm

-2

Введіть число та створіть Arraylist, а цикл while запише всі цифри у Arraylist. Тоді ми можемо вийняти розмір масиву, який буде довжиною цілого числа, яке ви ввели.

ArrayList<Integer> a=new ArrayList<>();

while(number > 0) 
{ 
    remainder = num % 10; 
    a.add(remainder);
    number = number / 10; 
} 

int m=a.size();

1
За винятком того, що вам не потрібен ArrayList або цифри.
Маркіз Лорн

-2

Ось дійсно простий метод, який я створив, який працює для будь-якого числа:

public static int numberLength(int userNumber) {

    int numberCounter = 10;
    boolean condition = true;
    int digitLength = 1;

    while (condition) {
        int numberRatio = userNumber / numberCounter;
        if (numberRatio < 1) {
            condition = false;
        } else {
            digitLength++;
            numberCounter *= 10;
        }
    }

    return digitLength; 
}

Як це працює із змінною лічильника чисел, це 10 = 1-значний пробіл. Наприклад .1 = 1 десята => 1-значний пробіл. Тому, якщо у вас є, int number = 103342;ви отримаєте 6, тому що це еквівалент .000001 пробілів назад. Також хтось має кращу назву змінноїnumberCounter ? Я не можу придумати нічого кращого.

Редагувати: Подумав лише про краще пояснення. По суті, це, що робить цикл, - це зробити так, щоб ви розділили число на 10, поки воно не стане менше одиниці. По суті, коли ви ділите щось на 10, ви переміщуєте його назад на один простір чисел, тому просто ділите його на 10, поки не досягнете <1 для кількості цифр у вашій кількості.

Ось ще одна версія, яка може рахувати кількість чисел у десятковій кількості:

public static int repeatingLength(double decimalNumber) {

    int numberCounter = 1;
    boolean condition = true;
    int digitLength = 1;

    while (condition) {
        double numberRatio = decimalNumber * numberCounter;

        if ((numberRatio - Math.round(numberRatio)) < 0.0000001) {
            condition = false;
        } else {
            digitLength++;
            numberCounter *= 10;
        }
    }
    return digitLength - 1;
}

-3

Спробуйте перетворити int в рядок, а потім отримати довжину рядка . Це повинно отримати довжину int .

public static int intLength(int num){
    String n = Integer.toString(num);
    int newNum = n.length();
    return newNum;
}

Це повністю еквівалентно вихідному коду. І промахнеться, коли numberнегативно.
Teepeemm
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.