Получение второй цифры из длинной переменной

Я пытаюсь извлечь вторую цифру из длинной переменной.

long mi = 110000000;
int firstDigit = 0;
String numStr = Long.toString(mi);
for (int i = 0; i < numStr.length(); i++) {
    System.out.println("" + i + " " + numStr.charAt(i));
    firstDigit =  numStr.charAt(1);
}

Когда я печатаю firstDigit = numStr.charAt(1) на консоли. Я получаю 1, который ожидается, но когда цикл заканчивается, firstDigit имеет 49. Немного смущает почему.

Ответ 1

Вы запутались, потому что 49 - значение ASCII целого числа 1. Таким образом, вы можете разделить символ на целое число, после чего вы можете увидеть целочисленное значение.

    Integer.parseInt(String.valueOf(mi).charAt(1)):

Ответ 2

Поскольку 49 - это значение ASCII char '1'.

Поэтому вы не должны напрямую назначать char int.

И вам здесь не нужен цикл, который в любом случае сохраняет ovveriding текущее значение с charAt(1).

int number = numStr.charAt(1) - '0'; // substracting ASCII start value 

Вышеприведенное утверждение внутренне работает как 49 -48 и дает вам 1.

Если вы чувствуете, что это смущает, как утверждают другие, используйте Character.getNumericValue();

Или, хотя мне не нравится ""+ hack, ниже должно работать

int secondDigit = Integer.parseInt("" + String.valueOf(mi).charAt(1));

Ответ 3

Вероятно, вы ищете Character.getNumericValue(...) i.e.

firstDigit = Character.getNumericValue(numStr.charAt(1));

В противном случае, поскольку переменная firstDigit имеет тип int, это означает, что вы назначаете ASCII-представление символа '1', который равен 49, а не целому числу по указанному индексу.

Также обратите внимание, что, поскольку вас интересует только конкретная цифра, нет необходимости вставлять оператор firstDigit = numStr.charAt(1); внутри цикла.

а просто сделайте следующее вне цикла.

int number = Character.getNumericValue(numStr.charAt(1));

Ответ 4

вам нужно только определить firstDigit как переменную типа char, поэтому напечатать в качестве символа. поскольку вы определяете как переменную int, это значение является значением ASCII char '1': 49. Вот почему вы получаете 49 вместо 1.

Ответ 5

ответ Integer.parseInt(String.valueOf(mi).charAt(1)+""); правильный.

Однако , если мы хотим рассмотреть performace в нашей программе, нам нужны некоторые улучшения.

Нам нужно много времени, Integer.parseInt() и String.valueOf(). И всегда пользовательские методы намного быстрее, чем Integer.parseInt() и String.valueOf(). см. простые тесты.

Таким образом, решение с высокой производительностью может выглядеть следующим образом:

int y=0;
while (mi>10)
{
    y=(int) (mi%10);
    mi=mi/10;
}
System.out.println("Answer is: " + y);

чтобы проверить его:

long mi=4642345432634278834L;
int y=0;

long start = System.nanoTime();

//first solution
//y=Integer.parseInt(String.valueOf(mi).charAt(1)+"");      

//seconf solution
while (mi>10)
{
    y=(int) (mi%10);
    mi=mi/10;
}

long finish = System.nanoTime();

long d = finish - start;
System.out.println("Answer is: " + y + " , Used time: " + d);

//about 821 to 1232 for while in 10 runs
//about 61225 to 76687 for parseInt in 10 runs

Ответ 6

Выполнение манипуляций с строками для работы с числами - это почти всегда неправильный подход.

Чтобы получить вторую цифру, используйте следующее:

int digitnum = 2;

int length = (int)Math.log10(mi));
int digit = (int)((mi/Math.pow(base,length-digitnum+1))%base);

Если вам нужна другая цифра, чем цифра второго изменения.

Чтобы избежать неопределенности в отношении чисел с плавающей запятой, вы можете использовать целочисленную математическую библиотеку, такую ​​как guavas IntMath

Ответ 7

Давайте посмотрим

System.out.println(numStr.charAt(1));
firstDigit =  numStr.charAt(1);
System.out.println(firstDigit);

Результат не будет таким же, как вы получите

1
49

Это происходит потому, что ваш firstDigit - int. Измените его на char, и вы получите ожидаемый результат

Ответ 8

Вы также можете сделать, как показано ниже,

firstDigit = Integer.parseInt( numStr.charAt(1)+"");

Таким образом, он будет печатать вторую цифру из длинного числа.

Ответ 9

Некоторые вещи, которые еще не были упомянуты:

  • Вторая цифра для целых типов данных undefined, если длинное число равно 0-9 (Нет, это не ноль. Целые числа не имеют десятичных знаков, это верно для чисел с плавающей запятой. Даже тогда вы должны вернуть undefined для NaN или значение бесконечности). В этом случае вы должны вернуть часового, например, например. -1, чтобы указать, что нет второй цифры.

  • Использование log10 для получения определенных цифр выглядит элегантно, но они являются 1. одной из наиболее дорогостоящих функций и 2. часто дают неверные результаты в случаях краев. Я дам несколько контрпримеров позже.

Производительность может быть улучшена далее:

public static int getSecondDigit(long value) {
long tmp = value >= 0 ? value : -value;
if (tmp < 10) {
  return -1;
}

long    bigNumber = 1000000000000000000L;
boolean isBig     = value >= bigNumber;

long  decrement   = isBig ? 100000000000000000L : 1;
long  firstDigit  = isBig ? bigNumber : 10;
int   result      = 0;
if (!isBig) {
  long test = 100;

  while (true) {
    if (test > value) {
      break;
    }
    decrement = firstDigit;
    firstDigit = test;
    test *= 10;
  }
}



// Remove first
while (tmp >= firstDigit) {
  tmp -= firstDigit;
}

// Count second
while (tmp >= decrement) {
  tmp -= decrement;
  result++;
}

return result;
}

Сравнение: 1 000 000 случайных длин.

String.valueOf()/Character.getNumericValue(): 106 мс
Log/Pow by Taemyr: 151 мс
Div10 от @Голамали-Иран: 45 мс
Рутина выше: 30 мс

Это еще не конец, это может быть еще быстрее при помощи таблиц поиска уменьшая 1/2/4/8, 10/20/40/80 и избегая использования умножения.

Ответ 10

попробуйте это, чтобы получить второй char из ваших длинных

mi.toString().charAt(1);

Ответ 11

Как получить код ASCII

int ascii = 'A';
int ascii = 'a';

Итак, если вы назначаете символ целому числу, целое число будет содержать значение ASCII этого символа. Здесь я явно дал значения, в вашем коде вы вызываете метод, который возвращает символ, поэтому вы получаете ASCII вместо цифры.