Calculating the nth Root in Java – 在Java中计算n次方根

最后修改: 2018年 10月 6日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Trying to find the n-th root in Java using pow() is inaccurate in some cases. The reason for that is that double numbers can lose precision on the way. Hence we may need to polish the result to handle these cases.

在Java中使用pow()试图找到n-th root,在某些情况下是不准确的。原因是,双数在途中可能会失去精度。因此,我们可能需要对结果进行抛光,以处理这些情况。

2. The Problem

2.问题

Suppose we want to calculate the N-th root as:

假设我们想计算第N个根为。

base = 125, exponent = 3

In other words, which number to the power of 3 is 125?

换句话说,哪个数字的3次方是125?

It’s provided that the n-th root of a number x is equal with the number x in the power of 1/n. So we translate our equation to:

它规定一个数字x的n次方根与数字x的1/n的幂相等。所以我们把我们的方程翻译成。

N-th root = Math.pow(125, 1/3)

The result is 4.999999999999999. And 4.999999999999999 to the power of 3 is not 125. So how do we fix that?

结果是4.9999999999999。而4.9999999999999到3的幂不是125。那么我们如何解决这个问题呢?

3. Calculating the N-th Root Correctly

3.正确地计算N次方根

The solution to the problem above is mostly a mathematic workaround, and it’s as simple as it gets. It’s well known that the n-th root of a number x is equal with the number x in the power of 1/n.

上述问题的解决方法主要是数学上的变通,而且简单得不能再简单。众所周知,数字x的n次方根与数字x的1/n的幂相等。

There are a few ways to leverage the equation above. First, we can use a BigDecimal and implement our version of the Newton-Raphson method. Secondly, we can round the result to the closest number and lastly, we can define a margin of error where the results will be acceptable. We’ll focus on the last two approaches.

有几种方法可以利用上面的方程。首先,我们可以使用BigDecimal并实现我们版本的Newton-Raphson方法。其次,我们可以将结果四舍五入到最接近的数字,最后,我们可以定义一个误差范围,使结果可以接受。我们将重点讨论后两种方法。

3.1. Round

3.1.圆

We’ll now use rounding to solve our problem. Let’s reuse our previous example and see how we can obtain the right result:

我们现在要用四舍五入的方法来解决我们的问题。让我们重新使用之前的例子,看看我们如何获得正确的结果。

public void whenBaseIs125AndNIs3_thenNthIs5() {
    double nth = Math.round(Math.pow(125, 1.0 / 3.0));
    assertEquals(5, nth, 0);
}

3.2. Margin of Error

3.2.误差范围

This approach is very similar to be above. We just need to define an acceptable error margin, suppose 0.00001:

这种方法与上述方法非常相似。我们只需要定义一个可接受的误差范围,假设是0.00001。

public void whenBaseIs625AndNIs4_thenNthIs5() {
    double nth = Math.pow(625, 1.0 / 4.0);
    assertEquals(5, nth, 0.00001);
}

The test proves that our methods correctly calculate the nth root.

该测试证明,我们的方法正确地计算了第n个根。

4. Conclusion

4.总结

As developers, we must understand the data types and their behavior. The math methods described above works really well with pretty good accuracy. You can choose the one that fits better your use case. The code for the solution above can be found over on GitHub.

作为开发者,我们必须了解数据类型和它们的行为。上面描述的数学方法真的很好用,精确度相当高。你可以选择一个更适合你的使用情况的方法。上述解决方案的代码可以在GitHub上找到over