【问题标题】:Calculate sum of the digits to the consecutive power in given number计算给定数字中连续幂的数字总和
【发布时间】:2017-02-13 21:44:29
【问题描述】:

在方法中计算数字总和与连续幂的最佳方法是什么?

例子:

calculateSum(5) -> returns 5^1 = 5
12 -> 1^1 + 2^2 = 5
26 -> 2^1 + 6^2 = 38
122 -> 1^1 + 2^2 + 2^3 = 13

我想使用流,因为我正在尝试练习一些 J8 功能,但找不到让它工作的方法。

编辑:我需要它来解决这个 kata:https://www.codewars.com/kata/5626b561280a42ecc50000d1/train/java

EDIT2:到目前为止,这是我的代码:

public static void calculateSum(int input) {
    String[] number = String.valueOf(input).split("");
    Map<Integer, Integer> map = Arrays.stream(number)
            .map(Integer::valueOf)
            .map(d -> (int) Math.pow(d, list.indexOf(d)))
            .collect(Collectors.toMap(d));
}

我不知道如何将来自number array 的数字与它们的连续幂进行映射,这样我就可以对那个映射中的值求和。

【问题讨论】:

  • 展示你尝试过的东西,然后我们可以从那里开始工作
  • 负整数?
  • 考虑Stream.reduce 或(考虑到“收集”一词出现在kata 中)Stream.collect。您可以将long 提供给reduce/collect 吗?如果没有,你能做些什么呢?
  • @smac89 添加了编辑。
  • @GrzegorzGórkiewicz 只是肯定的。

标签: java algorithm


【解决方案1】:

这是一个没有流的解决方案。

public static int digitPow(int n) {
    int result = 0;
    int count = (int)(Math.log10(n) + 1); // number of digits in n

    while (count > 0) {
        result += Math.pow((n % 10), count);
        n /= 10;
        count--;
    }

    return result;
}

【讨论】:

  • 您能解释一下您是如何使用 Math.log10 得出这个 int 计数的吗?太棒了,你的思考过程是什么?
  • @doublemc log10 是计算以 10 为底的位数的标准方法。
  • @doublemc 记录x 的基数b,其中x 是基数b 中的一个数字,告诉您之前可以将x 除以b 的次数它小于b。请注意,由于x 是基数b 中的一个数字,因此每次将x 除以b 时,都会从中删除一位数字。使用这些知识,您现在可以说以 10 为底的数字中的位数是该数字的以 10 为底的对数加 1。加一来自这样一个事实,即对数只会持续到数字小于基数,所以我们包括最后一位数字来给出完整的计数。
【解决方案2】:

这应该适合你:

```

String str = String.valueOf(122);
DoubleSummaryStatistics collect = IntStream.range(0, str.length()) //1
    .mapToObj(i -> {
        int digit = Character.digit(str.charAt(i), 10); //2
        return Math.pow(digit, i + 1); //3
    })
    .collect(Collectors.summarizingDouble(i -> i)); //4

System.out.println(collect.getSum());

```

  1. 生成功率值
  2. 从给定位置的字符中提取数字
  3. 计算提取数的幂
  4. 总结一切

【讨论】:

  • 我已经按照你的要求使用了流:)
【解决方案3】:

要修复您已有的问题,诀窍是使用IntStream

public static void calculateSum(int input) {
    String[] number = String.valueOf(input).split("");
    int sum = IntStream.range(0, number.length)
        .map(i -> (int)Math.pow(Integer.valueOf(number[i]), i + 1))
        .sum();

    System.out.println(sum)
}

【讨论】:

  • 比我的版本简单得多 :) 我看到了简单的代码,我赞成 :)
【解决方案4】:

仅供参考: Stream 不是解决此类问题的好方法。强制使用 Streams 是不好的编码。编写好的代码的一部分,是识别工作的正确工具,而 Stream 不是这里使用的工具。

为了防止double 不准确的任何潜在问题,这里是一个纯int 解决方案:

private static int calculateSum(int input) {
    if (input < 0)
        throw new IllegalArgumentException("Negative: " + input);
    int[] digit = new int[10], power = new int[10];
    for (int i = 0, n = input; n != 0; i++, n /= 10) {
        for (int j = 0; j < i; j++)
            power[j] *= digit[j];
        power[i] = digit[i] = n % 10;
    }
    int sum = 0;
    for (int i = 0; i < 10; i++)
        sum += power[i];
    if (sum < 0)
        throw new ArithmeticException("Overflow: " + input);
    return sum;
}

测试

public static void main(String[] args) {
    test(5);
    test(12);
    test(26);
    test(122);
    test(Integer.MAX_VALUE);
    test(1999999998);
}
private static void test(int input) {
    System.out.printf("%d -> %d%n", input, calculateSum(input));
}

输出

5 -> 5
12 -> 5
26 -> 38
122 -> 13
2147483647 -> 284684832
1999999998 -> 1509589865

请注意,以9 结尾的 10 位数字会溢出。

【讨论】:

  • 好吧,看看一些答案,流似乎非常强大(简短而简洁),几乎可以在我们需要处理数组、比较等的任何地方使用。
猜你喜欢
  • 1970-01-01
  • 2019-06-27
  • 1970-01-01
  • 1970-01-01
  • 2014-12-19
  • 2021-12-25
  • 1970-01-01
  • 2022-11-24
  • 2019-09-26
相关资源
最近更新 更多