如何获取整数的各个位数?

196

我有一些数字,比如1100、1002、1022等。我想要它们的每个数字位,例如对于第一个数字1100,我想获得1、1、0、0。

在Java中怎么做呢?

30个回答

259

为了做到这一点,您将使用%(模数)运算符。

int number; // = some int

while (number > 0) {
    print( number % 10);
    number = number / 10;
}

取模运算符将给出在对一个数进行整数除法后的余数。

所以,

10012 % 10 = 2

因为:

10012 / 10 = 1001, remainder 2

注意: 正如保罗所指出的,这将按相反的顺序给出数字。您需要将它们推入堆栈并按相反的顺序弹出。

以正确的顺序打印数字的代码:

int number; // = and int
LinkedList<Integer> stack = new LinkedList<Integer>();
while (number > 0) {
    stack.push( number % 10 );
    number = number / 10;
}

while (!stack.isEmpty()) {
    print(stack.pop());
}

4
这将给你带来错误顺序的数字,因此你需要确保将它们推入一个栈中或将它们以相反的顺序放入数组中。 - Paul Tomblin
4
请注意,这使得它们从右到左排列(与原帖示例从左到右的情况相反)。这很容易处理,但需要注意。 - James Curran
1
@Don,实际上不会。虽然它比基于字符串的版本快得多,但我不会支持它。我建议看一下Marimuthu的答案,其中包含一些快速简短的代码。 - jjnguy
3
很好的解决方法,但似乎无法处理数字以前导零开始的情况。例如 - 001122。如果我使用上述逻辑 - 我只会得到1,1,2,2。前导0被%和/运算符抛弃。如果我有误请纠正我。 - old_soul_on_the_run
3
负整数怎么办?如果我输入-3432,那么输出就会是-2-3-4-3,这是不正确的。 - Nodir Nasirov
显示剩余4条评论

84
将其转换为String并使用String#toCharArray()String#split()
String number = String.valueOf(someInt);

char[] digits1 = number.toCharArray();
// or:
String[] digits2 = number.split("(?<=.)");

如果您已经在使用Java 8,并且之后想要执行一些聚合操作,请考虑使用String#chars()将其转换为IntStream

IntStream chars = number.chars();

8
这是一种快速且简单的方法。 - jjnguy
9
使用 split(""),数组的第一项为 ""。可以尝试其他正则表达式,例如使用 split("(?<=.)") - True Soft
4
toCharArray比split快得多。我将它们都放在循环中执行了1000次,toCharArray花费了20毫秒,而split则花费了1021毫秒。我还使用除以十和取模(%)的数学方法进行了测试,这种方式需要50毫秒,因此toCharArray似乎比其他两种方法更快。 - Jerry Destremps
2
编辑:我又做了一遍,这次循环更长以确保准确性(10,000次迭代)。 toCharArray 比 split 快大约100倍,而 toCharArray 比取模数学方法快大约5倍。 - Jerry Destremps
9
@BalusC number.chars() 会返回 ASCII 值而不是数字。因此,数字 "1234" 将被拆分为 "49"、"50"、"51"、"52" 而不是 "1"、"2"、"3"、"4"。正确的写法应该是:IntStream chars = number.chars().map(Character::getNumericValue); - Koin Arab
显示剩余4条评论

34

这个怎么样?

public static void printDigits(int num) {
    if(num / 10 > 0) {
        printDigits(num / 10);
    }
    System.out.printf("%d ", num % 10);
}

或者,我们可以将输出内容存储在整数数组中,然后再打印该数组,而不是将其打印到控制台:

public static void main(String[] args) {
    Integer[] digits = getDigits(12345);
    System.out.println(Arrays.toString(digits));
}

public static Integer[] getDigits(int num) {
    List<Integer> digits = new ArrayList<Integer>();
    collectDigits(num, digits);
    return digits.toArray(new Integer[]{});
}

private static void collectDigits(int num, List<Integer> digits) {
    if(num / 10 > 0) {
        collectDigits(num / 10, digits);
    }
    digits.add(num % 10);
}

如果您想保持数字的顺序从最低位(索引[0])到最高位(索引[n]),则以下更新的getDigits()是您需要的:

/**
 * split an integer into its individual digits
 * NOTE: digits order is maintained - i.e. Least significant digit is at index[0]
 * @param num positive integer
 * @return array of digits
 */
public static Integer[] getDigits(int num) {
    if (num < 0) { return new Integer[0]; }
    List<Integer> digits = new ArrayList<Integer>();
    collectDigits(num, digits);
    Collections.reverse(digits);
    return digits.toArray(new Integer[]{});
}

1
这是使用模运算以正确顺序打印内容的好方法。 +1 - jjnguy
1
这很不错。我在想:“一定有一种不用集合就可以倒序的方法...” +1 - bobndrew
完美。可能需要添加以下代码到getDigits(int num)函数中,以使其免受错误输入的影响: if (number < 0) { return new Integer[0]; }使用以下输入进行测试: Integer[] samples = {11111, 123457, 0, -13334, 93846, 87892, 9876543, -1234, 012455}; - realPK

28

我没有看到有人使用这种方法,但它对我很有效,而且简单易行:

int num = 5542;
String number = String.valueOf(num);
for(int i = 0; i < number.length(); i++) {
    int j = Character.digit(number.charAt(i), 10);
    System.out.println("digit: " + j);
}

这将产生输出:

digit: 5
digit: 5
digit: 4
digit: 2

太棒了。谢谢。 - Marwa Eltayeb
由于某些原因,这个逻辑对于不同于5542的数字给出了错误的输出。例如尝试输入0142323。 - tavalendo
1
@tavalendo 0142323 是一个八进制常量,等于 50387,由于前导零,就像 0x100 是一个十六进制常量,等于 256,由于前导 0x,而 0b1011 是一个二进制常量,等于 11,由于前导 0b。请注意整数常量的前导 0! - AJNeufeld

18

我注意到使用Java 8流来解决问题的示例很少,但我认为这是最简单的示例:

int[] intTab = String.valueOf(number).chars().map(Character::getNumericValue).toArray();

明确一点: 你使用String.valueOf(number)将int转换为String,然后使用chars()方法获取一个IntStream(现在你字符串中的每个字符都是Ascii数字),然后需要运行map()方法获取Ascii数字的数值。最后使用toArray()方法将流转换为int[]数组。


14

我看到所有的答案都不太美观,也不是很干净。

我建议你使用一点递归来解决你的问题。这篇文章非常久远,但它可能对未来的编程人员有帮助。

public static void recursion(int number) {
    if(number > 0) {
        recursion(number/10);
        System.out.printf("%d   ", (number%10));
    }
}

输出:

Input: 12345

Output: 1   2   3   4   5 

你说得对,答案的确很丑陋。谢谢。 - parsecer

9
简单的解决方案。
public static void main(String[] args) {
    int v = 12345;
    while (v > 0){
        System.out.println(v % 10);
        v /= 10;
    }
}

6

由于我在这个问题上没有看到使用Java 8的方法,所以我想提供一下。假设你从一个String开始,并且希望获得一个List<Integer>,那么你可以像下面这样对元素进行流式处理。

List<Integer> digits = digitsInString.chars()
        .map(Character::getNumericValue)
        .boxed()
        .collect(Collectors.toList());

此代码将字符串中的字符作为IntStream获取,将这些字符的整数表示映射为数字值,装箱并将它们收集到列表中。


有趣的是,chars()返回一个IntStream,因此如果您调用boxed()和collect(),即可立刻返回整数列表。 - Jason
1
你得到ASCII值。所以1映射为49。 - ifly6
有趣!不知道,谢谢。 - Jason
无法编译:Collectors.toList() → "类型不匹配:无法从Collector<Object,capture#3-of ?,List<Object>>转换为Supplier<R>", collect → "IntStream中的方法collect(Supplier<R>, ObjIntConsumer<R>, BiConsumer<R,R>)对于参数(Collector<Object,?,List<Object>>)不适用" - Gerold Broser
编辑过的代码需要在收集之前进行框选。请参见 https://repl.it/@ifly6/HeftyAffectionateHertz#Main.java 的示例。 - ifly6

6
// could be any num this is a randomly generated one
int num = (int) (Math.random() * 1000);

// this will return each number to a int variable
int num1 = num % 10;
int num2 = num / 10 % 10;
int num3 = num /100 % 10;

// you could continue this pattern for 4,5,6 digit numbers
// dont need to print you could then use the new int values man other ways
System.out.print(num1);
System.out.print("\n" + num2);
System.out.print("\n" + num3);

Java中的int类型具有最小值为-2^31和最大值为2^31-1。如何使上述解决方案适用于所有适合int类型的正值? - realPK

5

Java 9引入了一个新的 Stream.iterate 方法,可以用来生成流并在特定条件下停止。这可以用于使用取模方法获取数字中的所有数字。

int[] a = IntStream.iterate(123400, i -> i > 0, i -> i / 10).map(i -> i % 10).toArray();

请注意,这将以相反的顺序获取数字,但这可以通过向后遍历数组(不幸的是,颠倒数组并不那么简单)或创建另一个流来解决:

int[] b = IntStream.iterate(a.length - 1, i -> i >= 0, i -> i - 1).map(i -> a[i]).toArray();

或者

int[] b = IntStream.rangeClosed(1, a.length).map(i -> a[a.length - i]).toArray();

作为例子,这段代码:
int[] a = IntStream.iterate(123400, i -> i > 0, i -> i / 10).map(i -> i % 10).toArray();
int[] b = IntStream.iterate(a.length - 1, i -> i >= 0, i -> i - 1).map(i -> a[i]).toArray();
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));

将会打印:

[0, 0, 4, 3, 2, 1]
[1, 2, 3, 4, 0, 0]

现在有一个不过度的解决方案!至少对于 000123-123,有一些有趣的结果 :-) - Kaplan
@Kaplan 这个问题是关于数字的,"-"不是一个数字。此外,数字"000123"和普通的"123"是一样的,除非你认为它是八进制或其他什么,但在这种情况下,它将成为完全不同的数字。 - Simon Forsberg
正如已经广泛讨论的那样,任何使用“%”的解决方法都存在省略前导零(例如“000123”)的缺陷。只是作为加演,我的解决方案也对符号起作用。顺便说一句:你的解决方案对于“000123”获得“[8,3]”。 - Kaplan
@Kaplan 这个问题是关于获取一个 int 数字的各个单独数字,而不是一个 String 数字。自然地,000123 变成了 83,因为 123 八进制等于 83 十进制。 - Simon Forsberg
唯一的任务是获取一个数字的数字,而不进行任何模糊的数字转换。因此,000123 变成了 [0, 0, 0, 1, 2, 3]。页面上没有其他人误解这个任务。 - Kaplan
@Kaplan 我没有误解任何事情。问题中没有指定应该如何处理前导零。此外,考虑到 int i = 000123; System.out.println(i); 打印出 83,我认为我的代码返回 [8, 3] 是完全合理的。 - Simon Forsberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接