Есть ли в j2se или в Джакарте что-то, что преобразует число в массив цифр? - PullRequest
1 голос
/ 31 июля 2009

Ненавижу кодировать то, что уже доступно. Я не могу найти в Джакарте обыкновенный метод, который бы:

long x= 12345;
int[] digits = toDigitsArray(x); //[1,2,3,4,5]

Итак, прежде чем я напишу свой собственный метод toDigitsArray (), кто-нибудь знает, существует ли эквивалент в j2se или в обыкновенных?

Ответы [ 6 ]

4 голосов
/ 31 июля 2009

Как насчет x.toString (). ToCharArray ()? Результатом будет массив символов, а не массив целых чисел, как вы, кажется, ищете в своем примере, но вы можете преобразовать символы в целые, как вы их использовали, или в зависимости от того, что вы пытаетесь с ним делать. , символы могут быть в порядке.

2 голосов
/ 31 июля 2009

Насколько я понимаю, такой функции не существует. У вас есть несколько ошибок, которые стоит обсудить.

Я проверил три параметра (разбиение строки и выполнение операции модуля и создание массива символов) через некоторые параметры, и это самый «эффективный» из всех, что я видел. Обратите внимание на некоторые предположения:

  1. Мы должны поддерживать Long
  2. Мы сохраняем тот факт, что знаковый бит числа, но не в массиве.

Сначала маршрут модуля, который на первый взгляд должен быть наиболее эффективным. Однако, если число действительно длинное (например, превышает максимальное значение типа int), то оператор мода переполняется и выдает нежелательные результаты. Итак, мы должны перейти к BigInteger (насколько я могу судить, если кто-то видит лучшее решение, прокомментируйте):

public static void main(String[] args) {
    long x = 981212131233123L;
    int[] r = new int[calculateSize(x)];
    boolean positive = fillArrayWithDigits(x, r);
    //r = [9, 8, 1, 2, 1 ...
}

    private static boolean fillArrayWithDigits(long y, int[] r) {
        boolean positive = y >= 0;
        y = Math.abs(y);
        BigInteger ten = BigInteger.valueOf(10);
        for (int i = r.length; i > 0; i--) {
            r[i-1] = BigInteger.valueOf(y).mod(ten).intValue();
            y /= 10L;
        }
        return positive;
    }

    private static int calculateSize(long y) {
        int size = 0;
        do {
            size++;
            y /= 10L;
        } while (y != 0);
        return size;
    }

В конце этого у вас есть логическое значение, указывающее, было ли число положительным, и массив, содержащий числа.

С точки зрения анализа строк самое лучшее, что я мог придумать, было:

public static void main(String[] args) {
    long x = 981212131233123L;
    boolean positive = x >= 0;
    x = Math.abs(x);
    String[] s = Long.toString(x).split("");
    int[] r = new int[s.length - 1];
    for (int i = r.length; i > 0; i--) {
        r[i-1] = Integer.parseInt(s[i]);
    }
    //r = [9, 8, 1, 2, 1 ...
}

Метод массива char был очень похож:

    public static void main(String[] args) {
        long x = 981212131233123L;
        boolean positive = x >= 0;
        x = Math.abs(x);
        char[] s = Long.toString(x).toCharArray();
        int[] r = new int[s.length];
        for (int i = r.length - 1; i > -1; i--) {
            r[i] = Character.digit(s[i], 10);
        }
        //r = [9, 8 ,1, 2, 1 ....
    }

но кажется наиболее эффективным

1 голос
/ 31 июля 2009

Я придумал 4 варианта метода.

  1. Использует String.toCharArray и Character.getNumericValue ()
  2. Использует модуль с массивом
  3. Использует модуль с Deque
  4. Использует String.split ()

При тестировании с очень большими значениями и Long.MAX_VALUE все четыре дают правильные результаты.

При тестировании с Long.MIN_VALUE выясняется, что Math.abs (Long.MIN_VALUE) == Long.MIN_VALUE, поэтому вы не можете полагаться на него, чтобы избавиться от знака минус !! Поэтому мне пришлось избавиться от этого, поэтому я изменил версии. Версии модуля также дают неправильные значения с Long.MIN_VALUE, цифры верны, но имеют все отрицательные знаки.

Что касается производительности, я провел несколько тестов, в которых я запускал каждый метод 10 000 000 раз с одним и тем же вводом, это примерный результат, но он очень типичен для других:

ввод: -5507235864653430347

1: 5110

2: 7235

3: 7564

4: 25487

Так что получается, что победителем пока является метод 1. 2 и 3 ненадежны, а 4 очень медленный.

public static int[] toIntArray(long x) {
    int neg = (x<0)?1:0;
    final char[] c = String.valueOf(x).toCharArray();
    final int s = c.length-neg;
    final int[] d = new int[s];
    for (int i = 0; i < s; i++) {
        d[i] = Character.getNumericValue(c[i+neg]);
    }
    if (neg==1) {
        d[0] = d[0] * -1;
    }
    return d;
}

public static int[] toIntArray2(long x) {
    int neg = (x<0)?1:0;
    final int s = String.valueOf(x).length()-neg;
    final int[] d = new int[s];
    for(int i =s-1 ; i > -1; i--) {
        d[i] = (int) (x%10);
        x = x/10;
    }
    return d;
}

public static Object[] toIntArray3(long x) {
    Deque<Integer> d = new ArrayDeque<Integer>(10);
    if(x==0){
        d.push(0);
        return d.toArray();
    }
    while(x != 0) {
        d.push((int) (x%10));
        x = x/10;
    }
    return  d.toArray();
}

public static int[] toIntArray4(long x) {
    int neg = (x<0)?1:0;
    final String[] c = String.valueOf(x).split("");
    final int s = c.length-neg;
    final int[] d = new int[s-1];
    for (int i = 1; i < s; i++) {
        d[i-1] = Integer.parseInt(c[i+neg]);
    }
    if (neg==1) {
        d[0] = d[0] * -1;
    }
    return d;
}
1 голос
/ 31 июля 2009

Я думаю, что это может сработать или, по крайней мере, увести вас дальше.

long x = 11234;
String[] s = Long.toString(x).split("");
int[] r = new int[s.length - 1];
for (int i = 1; i < s.length; i++)
  r[i - 1] = Integer.parseInt(s[i]);
1 голос
/ 31 июля 2009

Не видел ни одного.

Что-то вроде "while (n! = 0) {push (n% 10); n = n / 10}" должно быть достаточно.

Если вы не хотите связываться со списками, сделайте это дважды. Во-первых, чтобы вычислить количество записей в массиве, а во-вторых, чтобы заполнить массив.

0 голосов
/ 01 августа 2009

Во-первых, я не знаю ни одного существующего библиотечного метода, который делает то, что вы хотите, и я не могу придумать хороший способ поиска одного. (И если кто-то может решить эту проблему, они заслуживают Нобелевской премии !!)

Все ответы, которые включают создание / разбиение строк или использование BigInteger, излишне неэффективны. Вот мое решение:

public int[] toDigitsArray(long num) {
    if (num < 0) {
        throw new IllegalArgumentException("negative num");
    } else if (num == 0) {
        return new int[]{0};  // simplifies the rest of the code
    }
    int[] tmp = new int[20];  // big enough to hold all digits of Long.MAX_VALUE
    int i = tmp.length - 1;
    while (num != 0) {
        tmp[i--] = num % 10;
        num = num / 10;
    }
    int[] res = new int[tmp.length - i];
    System.arraycopy(tmp, i + 1, res.length, res, 0);
    return res;
}

(я не скомпилировал / не протестировал это ... но сосредоточился на алгоритме.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...