编写方法来查找数字的多维数据集根。你不应该使用Math.cbrt

时间:2017-01-03 02:57:56

标签: java math

这是我的代码。它也适用于某些浮动值。如125.5。

public class NewClass {
public static void main(String[] args){
    Scanner Input = new Scanner(System.in);
    NewClass ob = new NewClass();
    double n = Input.nextDouble();
    double cbrt = ob.Cbrt(n);
    System.out.println(cbrt);
}
public  double GetSquareRoot(double n, double low, double high) {
    double cbrt = (low + high) / 2;

    if (cbrt*cbrt*cbrt > n)
        return GetSquareRoot(n, low, cbrt);
    if (cbrt*cbrt*cbrt < n)
        return GetSquareRoot(n, cbrt, high);
    return cbrt;
}
    public double Cbrt(double n) {
        NewClass ob = new NewClass();
        return ob.GetSquareRoot(n, 0, n);
}
}

但输入

时,此代码无法给出正确答案
0.008 or 0.125 or 50 or 100

但是当我们给出输入125.5或125或8时,它提供了正确的解决方案。

有人可以帮助我吗?

2 个答案:

答案 0 :(得分:1)

错误就是这一行:

return ob.GetSquareRoot(n, 0, n);

(当然,这是错误名称)试图找到0和n之间的解决方案。但是,如果0 <0。 n &lt; 1,然后 n 1/3 &gt; n ,因此您永远不会在区间(0, n )中找到解决方案。你需要对此做一个特例;例如,如果0&lt; n &lt; 1,您可以搜索间隔( n ,1)。

另外,使用0和n作为边界将不适用于负数,所以如果你想让你的方法更完整并处理这些情况,那么你也需要特殊情况(可能不同于-1&lt; n &lt; 0和 n &lt; -1)。

更多信息:在看到您对StackOverflowError的评论后,我发现您还有其他问题:您希望获得准确的结果。放入0.008时,立方根为0.2。但是,0.008和0.2都不能完全表示为浮点数。结果是,如果你让cbrt =最接近0.2的值可以表示,那么cbrt*cbrt*cbrt将不会是0.008。它无论如何都不能正好是0.008,因为0.008不能表示为double;但是,如果n是最接近0.008的值,则由于舍入错误,cbrt*cbrt*cbrt可能不会完全等于n。对于这样的计算,重要的是比较双精度的相等性;相反,使用“epsilon”值或误差范围来比较它们。因此,在

之后
double cbrt = (low + high) / 2;

你应该有像

这样的东西
if (Math.abs(cbrt*cbrt*cbrt - n) < EPSILON)
    return cbrt;

其中EPSILON是一些小值,例如1E-10。 (我有时会看到EPSILON被计算为相对值的代码,即abs(n * RELATIVE_EPSILON),而不是绝对值。)

避免StackOverflowError的另一种方法是在lowhigh变得非常接近时退出,因为到那时你不会获得更多的准确性,而你需要即使cbrt*cbrt*cbrt的值有点偏离,也要确保退出算法。像

这样的东西
if (high - low < EPSILON)
    return cbrt;

另见What's wrong with using == to compare floats in Java?

答案 1 :(得分:-1)

//How about My Solution - Without Recursive

import java.util.Scanner;

public class CubeRoot {

public static void main(String[] args) {
    Scanner input = new Scanner(System.in);
    String str = input.next();
    Boolean negative = false;
    if (str.startsWith("-")) {
        str = str.substring(1);
        negative = true;
    }
    if (str.indexOf(".") > 0) {
        // find the poisition of '.'
        int pPos = str.length() - 1 - str.indexOf(".");
        String plainStr = (str.substring(0, str.indexOf('.')).concat(str.substring(str.indexOf('.') + 1)));
        StringBuffer cStr = new StringBuffer(cubeRoot(plainStr));

        if (cStr.toString().equalsIgnoreCase(plainStr))
            System.out.println("couldn't compute Cube Root for this :(");
        else {
            if (cStr.length() > pPos / 3) // devide 3 times to put the '.'
                cStr.insert(cStr.length() - pPos / 3, ".");
            else {
                int cStrLength = cStr.length();
                for (int i = 0; i <= pPos / 3 - cStrLength; i++)
                    cStr = new StringBuffer("0").append(cStr.toString());
                cStr.insert(cStr.length() - pPos / 3, ".");
            }
            String append = (negative) ? new String("-") : new String("");
            System.out.println(append + cStr.toString());
        }
    } else {
        System.out.println("Not a floating num");
    }
}

private static String cubeRoot(String d) {
    Long l = new Long(d);
    for (int i = 0; i < l; i++) {
        if (i * i * i == l) {
            return String.valueOf(i);
        }
    }
    return d;

}

}