这是我的代码。它也适用于某些浮动值。如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时,它提供了正确的解决方案。
有人可以帮助我吗?
答案 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
的另一种方法是在low
和high
变得非常接近时退出,因为到那时你不会获得更多的准确性,而你需要即使cbrt*cbrt*cbrt
的值有点偏离,也要确保退出算法。像
if (high - low < EPSILON)
return cbrt;
答案 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;
}
}