优化-快速计算一个数的立方根

880 阅读1分钟

方法一:牛顿迭代法

假设有一个数A,求这个数A的立方根。

这个问题就可以转换为一个数的立方与数A之间的函数

f(x)=x3af(x) = x^3-a

对函数做泰勒展开

f(x)=f(x0)+f(x0)(xx0)+f(ξ)2ξxx0之间f(x) = f(x_0) + f^{'}(x_0)(x-x_0)+\frac{f^{''}(\xi)}{2!},\xi 在x与x_0之间

我们可以得出一个近似的公式

xn+1=xnf(xn)f(xn)x_{n+1} = x_n - \frac{f(x_n)}{f^{'}(x_n)}

通过迭代,每次产生下一个x,来逼近真正我们需要的值。注意x不能等于0.

xn+1=xnx3a3x2x_{n+1} = x_n-\frac{x^{3}-a}{3x^{2}}
 public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String testStr = br.readLine().trim();
        double i = Double.parseDouble(testStr);
        boolean positive = true;
        // 处理正负数
        if(i<0){
            positive = false;
            i = -i;
        }
        double x = 1;
        while (Math.abs(x * x *x - i) > 0.0001){
            x = x - (x * x *x - i)/(3*x*x);
        }
        if(!positive){
            x = -x;
        }
        System.out.println(String.format("%.1f",x));
    }

方法二

牛顿法简单易懂,但是迭代次数较多,下面这个方法可以快速的逼近,原理就是先快速定位一个距离,每次增减距离都是10的倍数,然后在目标值之间来回摆动,直到距离小于某个精度。

 public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        double i = Double.parseDouble(br.readLine());
        boolean positive = false;
        if (i < 0) {
            positive = true;
            i = -i;
        }
        double distance = i;
        double index = 0;
        double last = 0;
        while (true) {
            last = index * index * index;
            if (last > i) {
                // 超过给定的值,缩小distance
                index -= distance;
                // 10的速度开始递减
                distance /= 10; 
            }
            // 满足精度即可退出
            if (distance < 0.001) {
                break;
            }
            // 小于给定值,增加distance
            index += distance;
        }
        double result = (int) ((index + 0.05) * 10) / 10.0;
        if (positive) {
            result =  - result;
        }
        System.out.println(result);
 }