首页 > 试题广场 >

求解立方根

[编程题]求解立方根
  • 热度指数:324950 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
计算一个浮点数的立方根,不使用库函数。
保留一位小数。

数据范围:


输入描述:

待求解参数,为double类型(一个实数)



输出描述:

输出参数的立方根。保留一位小数。

示例1

输入

19.9

输出

2.7
示例2

输入

2.7

输出

1.4
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        double x = in.nextDouble();
        double delta = 0.01;  // 精度
        // 考虑|x|>1的情况和|x|<1的情况,前者立方根比原数小,后者比原数大
        double left = x > 0? 0: x < -1? x: -1;
        double right = x > 0? x > 1? x: 1: 0;
        while (right*right*right-x>delta) {
            double mid = (left + right) / 2;
            if (mid*mid*mid > x) {
                right = mid;
            } else if (mid*mid*mid < x) {
                left = mid;
            }
        }
        System.out.printf("%.1f", right);
    }
}
发表于 2024-10-03 14:39:59 回复(0)
// 答案来自题解
// 如果一个数num>1,那么这个数的立方根一定在1~num之间。
// 如果一个数num<-1,那么这个数的立方根一定在num~-1
// 如果一个数-1<num<1,那么这个数的立方根一定在-1~1之间
// 例如:num = 2.7 可以设置左边界为min(-1,2.7) = -1 右边界 max(1,2.7) = 2.7 所以left = -1,right = 2.

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNext()) { // 注意 while 处理多个 case
            double a = in.nextDouble();
            // 二分法
            double x = binarySearch(a);
            System.out.printf("%.1f", x);
        }
    }
    public static double binarySearch(double num) {
        double left = Math.min(-1, num);
        double right = Math.max(1, num);
        double mid = 0.0;

        // 无限逼近,当right 和 left 精度小于0.0001了说明left的值就逼近答案的值
        while (right - left > 0.001) {
            mid = (right + left) / 2;
            if (mid * mid * mid > num) {
                right = mid;
            } else if (mid * mid * mid < num) {
                left = mid;
            } else {
                return mid; // 相等情况,直接退出
            }
        }
        return left;
    }
}
发表于 2024-09-11 11:40:45 回复(0)
不用库方法,我用库方法的源码
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    private static final int B1 = 715094163; /* B1 = (682-0.03306235651)*2**20 */
    private static final int B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */

    private static final double C =  0x1.15f15f15f15f1p-1; //   19/35   ~= 5.42857142857142815906e-01
    private static final double D = -0x1.691de2532c834p-1; // -864/1225 ~= 7.05306122448979611050e-01
    private static final double E =  0x1.6a0ea0ea0ea0fp0;  //   99/70   ~= 1.41428571428571436819e+00
    private static final double F =  0x1.9b6db6db6db6ep0;  //   45/28   ~= 1.60714285714285720630e+00
    private static final double G =  0x1.6db6db6db6db7p-2; //    5/14   ~= 3.57142857142857150787e-01

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        double aDouble = scanner.nextDouble();
        double compute = compute(aDouble);
        double l = Math.round(compute * 10) / 10.0;
        Math.cbrt(12);
        System.out.println(l);
    }


    public static double compute(double x) {
        double  t = 0.0;
        double sign;

        if (x == 0.0 || !Double.isFinite(x))
            return x; // Handles signed zeros properly

        sign = (x < 0.0) ? -1.0:  1.0;

        x = Math.abs(x);   // x <- |x|

        // Rough cbrt to 5 bits
        if (x < 0x1.0p-1022) {     // subnormal number
            t = 0x1.0p54;          // set t= 2**54
            t *= x;
            t = __HI(t, __HI(t)/3 + B2);
        } else {
            int hx = __HI(x);           // high word of x
            t = __HI(t, hx/3 + B1);
        }

        // New cbrt to 23 bits, may be implemented in single precision
        double  r, s, w;
        r = t * t/x;
        s = C + r*t;
        t *= G + F/(s + E + D/s);

        // Chopped to 20 bits and make it larger than cbrt(x)
        t = __LO(t, 0);
        t = __HI(t, __HI(t) + 0x00000001);

        // One step newton iteration to 53 bits with error less than 0.667 ulps
        s = t * t;          // t*t is exact
        r = x / s;
        w = t + t;
        r = (r - t)/(w + r);  // r-s is exact
        t = t + t*r;

        // Restore the original sign bit
        return sign * t;
    }

    private static double __HI(double x, int high) {
        long transX = Double.doubleToRawLongBits(x);
        return Double.longBitsToDouble((transX & 0x0000_0000_FFFF_FFFFL) |
                ( ((long)high)) << 32 );
    }

    private static double __LO(double x, int low) {
        long transX = Double.doubleToRawLongBits(x);
        return Double.longBitsToDouble((transX & 0xFFFF_FFFF_0000_0000L) |
                (low    & 0x0000_0000_FFFF_FFFFL));
    }

    private static int __HI(double x) {
        long transducer = Double.doubleToRawLongBits(x);
        return (int)(transducer >> 32);
    }
}

发表于 2024-08-11 12:06:14 回复(1)
import java.util.Scanner;
//牛顿迭代,注意while里的条件,是真实值和估计值的差值的绝对值小于误差

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        double n = in.nextDouble();
        double error = 0.0000001;
        double start = n/3;
        double value;
        while(start*start*start - n > error || n - start*start*start > error){
            start = start - (start*start*start-n)/(start*start*3);
        }
        System.out.print(String.format("%.1f", start));
    }
}

发表于 2024-08-10 01:03:47 回复(0)
一个需要知道牛顿法;另一个需要知道保留一位小数 #.# ,使用 DecimalFormat

编辑于 2024-04-05 17:29:18 回复(0)
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        double num = in.nextDouble();
        boolean fushu = false;
        if(num < 0){
            fushu = true;
            num = num * (-1.0);
        }
        double ans = 0.0;
        for(double i = 0 ; i < 5; i++){
            if(i * i * i < num && (i+1) * (i+1) *(i+1) > num){
                ans = i;
                break;
            }
        }
       
        //不处理四舍五入直接保留
        for( ; ; ){
            ans = ans + 0.1;
            if(((ans-0.1) * (ans-0.1) * (ans-0.1) < num) && (ans * ans * ans > num) ){
                ans = ans - 0.1;
                break;
            }
        }
        double tmp = ans;

        //要处理四舍五入
        for( ; ; ){
            ans = ans + 0.01;
            if(((ans-0.01) * (ans-0.01) * (ans-0.01) < num) && (ans * ans * ans > num) ){
                if(ans - tmp > 0.05){
                    ans = tmp + 0.1;
                }else{
                    ans = tmp;
                }
                break;
            }
        }
        if(fushu){
            ans = ans * (-1.0);
        }
        System.out.print(String.format("%.1f",ans));
       
    }
}
发表于 2024-01-11 17:58:31 回复(0)
用例3:输入12,输出2.3。
经计算:2.3*2.3*2.3=12.167
我给的输出是2.2
我是截断输出的,用例肯定是进位了吧?这答案怎么算正确?晕……
发表于 2024-01-10 19:28:31 回复(3)
import java.util.Scanner;

import java.io.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args)throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        Double num = Double.parseDouble(br.readLine());
        Double k = 1d;
        Double num1 = 0d;
        if (num == 0 ) {
            System.out.println(0);
            return;
        }
        if (num > 0) {
            for (Double i = 1d;; i += k) {
                if (i * i * i == num) {
                    System.out.printf("%.1f", i);
                    return;
                } else if (i * i * i > num) {
                    i = i - k;
                    k = k / 10;
                    if (k == 0.0001) {
                        num1 = i;
                        break;
                    }
                }
            }
        }
        if (num < 0) {
            for (Double i = -1d;; i -= k) {
                if (i * i * i == num) {
                    System.out.printf("%.1f", i);
                    return;
                } else if (i * i * i < num) {
                    i = i + k;
                    k = k / 10;
                    if (k == 0.0001) {
                        num1 = i;
                        break;
                    }
                }
            }
        }

        System.out.println(String.format("%.1f", num1));
        String str = num1.toString();

    }
}求大佬指点
发表于 2023-09-19 22:04:14 回复(0)
import java.math.BigDecimal;
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextDouble()) { // 注意 while 处理多个 case
            Double dou = in.nextDouble();
            for (double i = 0; i <= 20; i = add(i)) {
                if (mul(i) > Math.abs(dou)) {
                    if(dou>0){
                        System.out.println(String.format("%.1f", sub(i)));
                    }else{
                        System.out.println("-"+String.format("%.1f", sub(i)));
                    }
                   
                    return;
                }
            }
        }

    }
    public static double add( double d1 ) {
        BigDecimal value1 = new BigDecimal( Double.toString(d1) );
        BigDecimal value2 = new BigDecimal( Double.toString(0.01) );
        return value1.add(value2).doubleValue();
    }
    public static double sub( double d1 ) {
        BigDecimal value1 = new BigDecimal( Double.toString(d1) );
        BigDecimal value2 = new BigDecimal( Double.toString(0.01) );
        return value1.subtract(value2).doubleValue();
    }
    public static Double mul( double d1 ) {
        BigDecimal value1 = new BigDecimal( Double.toString(d1) );
        return value1.multiply(value1).multiply(value1).doubleValue();
    }
}
发表于 2023-08-28 12:54:06 回复(1)
// 穷举,笨人用笨方法
public static double resolve(double value) {
    if (value == 0d || value == 1d || value == -1d) {
        return value;
    }
    if (value == 8d || value == -8d) {
        return value > 0 ? 2 : -2;
    }
    boolean positive = true;
    if (value < 0) {
        positive = false;
        value = -value;
    }
    double c = 1e-3; // 误差
    boolean isDecimal = value < 1;
    double base = isDecimal ? 1 : 0;
    double max = isDecimal ? 1 : value, min = isDecimal ? value : 1;
    while (true) {
        double cube = base * base * base;
        boolean bigger = value > cube;
        double sub = bigger ? value - cube : cube - value;
        if (sub <= c) {
            break;
        }
        if (bigger) {
            min = base;
        } else {
            max = base;
        }
        base = (max + min) / 2;
    }
    return positive ? base : -base;
}
发表于 2023-07-23 14:38:06 回复(0)
立方的曲线是单调的,可以用二分查找在[-20, 20]内试探x*x*x 与输入的差值是不是接近0,

import java.util.Scanner;

public class HJ107 {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		//in.hasNextInt();
		double a = in.nextDouble();


		search(-20.0, 20, a);
	}

	public static void  search(double l, double r, double t) {
		double m = (l + r) / 2.0;

		double v = m*m*m;
		if (Math.abs(t -v) < 0.0000001) {
			System.out.printf("%.1f", m);
		} else if (v > t) {
			search(l, m, t);
		} else {
			search(m, r, t);
		}
	}

}

发表于 2023-06-16 14:33:50 回复(0)
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        System.out.print(String.format("%.1f",Math.cbrt(in.nextDouble())));
    }
}

发表于 2023-06-07 11:21:00 回复(1)
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextDouble()) { // 注意 while 处理多个 case
            Double num = in.nextDouble();

            System.out.println(getNum(num));
        }
    }

    public static double getNum(double num) { //20
            if (num == 0) {
                return 0;
            }
            boolean fushu = false;//判断负数
            if (num < 0) { //如果是负数
                num = 0 - num;
                fushu = true;
            }
            boolean xiaoshu = false;//判断纯小数
            if (num > 0 && num < 1) {
                num = 1000 * num;//注意1:乘以1000,立方根除以10就可以
                xiaoshu = true;
            }
            double half = num / 2; //10
            double lf = half * half * half;//1000
            double start = 0;
            double end = half;//10
            double half2 = 0;
            //注意2:该循环体只能计算出大于1的数的立方根
            while (!(lf > (num - 0.01) && lf < (num + 0.01))) { //注意3:并不一定能完全相等,需要满足一定范围就可以;
                half2 = (start + end) / 2; //5
                if (half2 * half2 * half2 >
                        num) { //注意4:如果最新的二分点在立方根右侧,则新的起点是这个二分值的一半,终点是这个二分值
                    start = half2 / 2; //2.5
                    end = half2;//5
                } else {
                    start = half2;//注意5:如果最新的二分点在立方根左侧,则新的起点是这个二分值,终点是上一个二分值,也就是end不变
                    end = end;
                }
                lf = half2 * half2 * half2;//注意6:重新计算当前的二分值是否满足循环条件;
            }
            if (fushu) { //如果是负数
                half2 = 0 - half2;
            }
            if (xiaoshu) { //如果是小数
                half2 = half2 / 10;
            }
            return Math.round(10 * half2) /10.0; //注意7:要写10.0否则写10会损失精度
        }
}
发表于 2023-04-29 17:21:47 回复(0)
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        double num = in.nextDouble();
        double rs = -5;
        while (rs * rs * rs < num) {
            rs += 0.01;
        }
        System.out.print(String.format("%.1f",rs));
    }
}
发表于 2023-04-13 11:09:03 回复(2)
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {

    static double result = 0;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        double data = 0;
        while (in.hasNext()) { // 注意 while 处理多个 case
            data = Double.parseDouble(in.next());
            break;
        }
        if (data > 0) {
            getValue(data, 0, (int)data + 1);
        } else {
            getValue(data,  (int)data - 1, 0);
        }
        System.out.println(result);
    }

    // 输入 取整 int()
    private  static void getValue(double target, double start, double end) {
        // 计算当前的值是不是相等
        double mid = (start + end) / 2;
        double value = mid * mid * mid;
        String parseStr = String.format("%.2f", value);
        value = Double.parseDouble(parseStr);
        if (value == target) {
            result = Double.parseDouble(String.format("%.1f", mid));
            return;
        }
        if (value > target) {
            getValue(target, start, mid - 0.1 );
        } else {
            getValue(target, mid + 0.1, end);
        }
    }

}

发表于 2023-03-20 19:22:44 回复(0)
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        double num = in.nextDouble();
        //记录是正数还是负数
        double sign = 1;
        double result = 0;
        //不管正负,都取正,以方便运算
        if(num<0){
            sign = -1;
            num *= -1;
        }
        //由于|val|<=20,所以我们可以知道,它的立方根是在(0,3)
        //根据输入值的范围,将情况分为三种
        //0<=num<1,在[0,1)范围内找
        //1<=num<8, 在[1,2)范围内找
        //8<=num<20,在[2,3)范围内找
        if(num>=0 && num<1){
            result = deCub(num,0);
        }else if(num>=1 && num<8){
            result = deCub(num,1);
        }else{
            result = deCub(num,2);
        }
        //别忘了乘上sign,以及保留一位小数
        System.out.println(String.format("%.1f",result*sign));
    }
    public static double deCub(double num, double low){
        //建立一个数组来存储节点值的立方和num之间的差值
        double[] distance = new double[10];
        //节点值的立方
        double cub = 0;
        //临时最小值
        double temp = num;
        //记录差值最小值所对应节点值
        int flag = 0;

        //从起始值low开始,每次增加0.1,记录差值,并和temp做比较,更新temp值和flag
        for(int i=0; i<10; i++){
            cub = Math.pow(low+i*0.1,3);
            distance[i] = Math.abs(num-cub);
            if(distance[i]<temp){
                temp = distance[i];
                flag = i;
            }
        }
        return low+flag*0.1;
    }
}


发表于 2023-03-02 17:33:50 回复(0)
因为输入的实数,因此要考虑负数,0-1的实数,>1的实数;负数取绝对值,按照正数处理;0-1的右边根应该取1;>1的右边根应该取输入的数本身
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 获取输入的实数
        String num = in.nextLine();
        // 定义一个数表示该立方根的左边和右边无限接近的数,只要右边-左边精度在0.0001,则可求得立方根
        double left = 0;
        double right;
        if (Math.abs(Double.parseDouble(num)) > 1) {
            right = Math.abs(Double.parseDouble(num));
        } else {
            right = 1;
        }
        // 定义一个立方根
        double mid = 0;
        while (right - left > 0.0001) {
            mid = (right + left) / 2;
            if (mid * mid * mid > Math.abs(Double.parseDouble(num))) {
                // 立方根较大,右边数降低为mid
                right = mid;
            } else {
                // 立方根较小,左边数升高为mid
                left = mid;
            }
        }
        if (num.contains("-")) {
            // 输出结果,保留一位小数
            System.out.print( "-");
            System.out.printf("%.1f", mid);
        } else {
            // 输出结果,保留一位小数
            System.out.printf("%.1f", mid);
        }

    }
}


发表于 2023-02-14 14:26:54 回复(0)
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNext()) { // 注意 while 处理多个 case
            Float a = in.nextFloat();
            double res = 0;
            if(a>0){while(res*res*res<a){res+=0.01;}}
            if(a<0){while(res*res*res>a){res-=0.01;}}
            System.out.println(String.format("%.1f",res));
        }
    }
}
发表于 2022-11-13 02:33:09 回复(1)

问题信息

难度:
79条回答 58903浏览

热门推荐

通过挑战的用户

查看代码
求解立方根