代码之家  ›  专栏  ›  技术社区  ›  Saikat SHASHANK HONRAO

如何用Java 8流/lambda计算整数中的尾零数?

  •  2
  • Saikat SHASHANK HONRAO  · 技术社区  · 7 年前

    如何用Java 8流/lambda计算整数中的尾零数?

    基本上逻辑应该是:保持整数除以 10 只要剩下的 0 (商将提供给下一个除法)并计算出现次数。

    例如

    12300 % 10 == 0 true

    1230 % 10 == 0

    123 % 10 == 0 false

    答: 2

    注: 我不喜欢这里涉及字符串:—)

    3 回复  |  直到 7 年前
        1
  •  3
  •   SergGr    7 年前

    如果这是一个纯粹的假设性问题,下面是一个纯粹的假设性答案,说明您如何做到这一点:

    static int countZeroes(int value) {
        if(value == 0) // we need to handle this case explicitly
            return 1; 
        IntStream s = IntStream.iterate(value, v -> v / 10);
        return (int) takeWhile(s, v -> v > 0 && v % 10 == 0)
                .count();
    
    }
    

    它使用一个助手函数 takeWhile 这在Java 9中可用,而不是在Java 8中可用,所以必须这样仿真:

    // In Java 9 there is a standard takeWhile
    // https://docs.oracle.com/javase/9/docs/api/java/util/stream/Stream.html#takeWhile-java.util.function.Predicate-
    // but in Java 8 I have to emulate it
    static IntStream takeWhile(IntStream s, final IntPredicate pr) {
        final Spliterator.OfInt origSp = s.spliterator();
    
        Spliterator.OfInt filtered = new Spliterators.AbstractIntSpliterator(origSp.estimateSize(), 0) {
            boolean lastPredicate = true;
    
            @Override
            public boolean tryAdvance(final IntConsumer action) {
                if (!lastPredicate)
                    return false;
    
                origSp.tryAdvance((int v) -> {
                    lastPredicate = pr.test(v);
                    if (lastPredicate) {
                        action.accept(v);
                    }
                });
                return lastPredicate;
            }
        };
    
        return StreamSupport.intStream(filtered, false);
    }
    

    想法是

    IntStream.iterate(value, v1 -> v1 / 10).takeWhile(v -> v > 0)
    

    应该在末尾一个接一个地生成一个切割数字流,然后您可以应用 takeWhile(v -> v % 10 == 0).count() 为了计算零的数目,最后你可以合并这两个 取而代之 S成一体。

        2
  •  1
  •   ETO    7 年前

    考虑到你没有 Java9 takeWhile 方法,这也可以做到:

    static final int[] POWERS_OF_10 = { 1000000000, 100000000, 10000000,
            1000000, 100000, 10000, 1000, 100, 10 };
    
    static int trailingZeros(int number) {
        return Arrays.stream(POWERS_OF_10)      // reversed stream of of 10^n
                     .map(pow -> number % pow)  // stream of rests
                     .reduce(0, (count, rest) -> (rest == 0) ? count + 1 : 0);
    }
    
        3
  •  1
  •   Kartik    7 年前

    另一种方法是:

    private static int countTrailingZeroes(int n) {
        int length = n == 0 ? 1 : (int) (Math.log10(n) + 1); //number of digits in n
        return IntStream.rangeClosed(0, length)
                .map(i -> length - i)           //reverse stream
                .map(o -> (int) Math.pow(10, o))
                .filter(o -> n % o == 0)
                .boxed()
                .findFirst()
                .map(i -> (int) Math.log10(i))  //number of digits minus 1
                .orElse(0);
    }
    

    @霍格尔的编辑:

    private static int countTrailingZeroes(int n) {
        int length = n == 0 ? 1 : (int) (Math.log10(n) + 1); //number of digits in n
        return IntStream.rangeClosed(0, length)
                .map(i -> length - i)           //reverse stream
                .filter(o -> n % (int) Math.pow(10, o) == 0)
                .findFirst()
                .orElse(0);
    }