一个求解平方根的算法题

1. 问题描述

问题是这样子的,给定一个数a,求解这个数的平方根,要求精度f<0.0001.

好久没有操刀实现算法代码了,今天就来写一个小的,后续算法依旧是研究的重点。比较软件中,算法是核心是灵魂啊!

2. 算法分析

说起来,这个算法题其实不是太麻烦,主要采取的就是不断试探,逼近真是目标值的思路,最容易想到的就是,不断的折半逼近,有点类似二分的思想。同时,一个重要的思想:

1. 设目标值平方根为Se

2. 待求解的输入数据为St

3. |Se*Se - St| < f*f

4. 求出一个Se*Se - St > 0的情况下的Se值,因为平方根分正负两个值,求出一个即可,这里求正值

3. 实现过程

这里,直接上JAVA的实现代码,注意,这里只实现了平方根大于1的问题场景,至于平方根在0~1之间这种场景,未处理!

package pingFangGeng;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

/**
 * @author shihuc
 * @date  2018年6月19日 上午8:31:51
 *
 * 本算法近似计算一个大于1的数字的平方根
 */
public class Solution {

    /**
     * @author shihuc
     * @param args
     */
    public static void main(String[] args) {
        Scanner scan = null;
        try {
            scan = new Scanner(new File("./src/pingFangGeng/input.txt"));
            int count = scan.nextInt();
            for(int i = 0; i < count; i++){
                int source = scan.nextInt();
                double fraction = scan.nextDouble();
                double res = binDivFind(0, source, source, fraction*fraction);
                System.out.println("No." + i + ": source=" + source + ", fraction=" + fraction + ", result=" + res);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (scan != null){
                scan.close();
            }
        }
    }

    /**
     * 算法思路:
     * |Se*Se - St| < fraction*fraction
     * 其中Se为目标值,St为给定待求解的数据,fraction为给定的精度
     *
     * @author shihuc
     * @param src
     * @param fraction
     * @return
     */
    private static double binDivFind(double st, double ed, double tar, double fraction) {
        double Se = (double) ((st + ed) / 2);
        double Se2 =  Se * Se;
        double Set = Se2 - tar;
        double res = Set * Set;
        double rval = Se;
        if(res >= fraction){
            if(Set > 0){
                rval = binDivFind(st, Se, tar, fraction);
            }else{
                rval = binDivFind(Se, ed, tar, fraction);
            }
        }
        return rval;
    }

}

代码中的测试用例,请看下面的文件:

6
9876543 0.0001
33 0.001
999 0.0001
777 0.00001
8888 0.001
1000000 0.0001

测试运行的结果,如下:

No.0: source=9876543, fraction=1.0E-4, result=3142.696771881704
No.1: source=33, fraction=0.001, result=5.744636535644531
No.2: source=999, fraction=1.0E-4, result=31.606961332261562
No.3: source=777, fraction=1.0E-5, result=27.874719826038927
No.4: source=8888, fraction=0.001, result=94.27618705481291
No.5: source=1000000, fraction=1.0E-4, result=999.9999999763531

分析与总结:

1. 整个算法实现,主要是通过递归的思路,不断折半试探,逐步逼近目标值。

2. 待求解数据,在算法实现过程中,若用float的数据类型,则会出现较大的误差,采用double的话,精度可信。

3. 0~1之间平方根的场景,只需将当前的算法做一个反向思路实现,因为0~1之间的数,平方后的数比元素数还要小。

原文地址:https://www.cnblogs.com/shihuc/p/9202564.html

时间: 2024-10-11 18:31:52

一个求解平方根的算法题的相关文章

记一道毫无思路的算法题

今天贤内给了我一道很实际的算法题,把我彻底难住了,实在想不出来,于是写此博文以记之. 背景是这样的,现在有一个付款明细的Excel,里面有为哪个发票,哪个公司应付多少钱的明细,明细数据是62条,现在知道我们已经付出的金额为Sum,请问到底哪些发票是已付款的. 这是62条明细数据: 653165.00 356029.11 220896.45 146362.00 1847670.00 3018518.91 1347553.07 145010.74 339784.84 199350.28 120611

Nim Game,一个有趣的游戏,也是一道入门算法题。

Nim Game,其实很多人都玩过.其实就是我们玩的划线游戏. 一张纸上,画若干条线,双方一人划一次,每次划掉1~3条线.可以选择画1条,也可以划2条,也可以3条.具体划去几条线完全看自己的策略.谁划掉最后一条线,就是赢家. 如上图,蓝方获胜. 正在看这篇文章的你一定是一个聪明人,每一步都是最优解,而你的对手,也跟你一样聪明,每步都是最优的解法. 现在你作为先手,在线条总数为多少的时候,你必赢呢,又在多少的时候必输呢? 可不可以用一个函数来判断在线条总是为x时你的输赢情况呢?这样你以后跟别人玩这

笔试算法题(35):最长递增子序列 &amp; 判定一个字符串是否可由另一个字符串旋转得到

出题:求数组中最长递增子序列的长度(递增子序列的元素可以不相连): 分析: 解法1:应用DP之前需要确定当前问题是否具有无后效性,也就是每个状态都是对之前状态的一个总结,之后的状态仅会受到前一个状态的影响:对于递增子序列 而言,可以首先确定前面k个元素的最长子序列,然后计算增加一个元素之后的最长子序列.由于每个位置i都会与0-i的每个位置之前的LIS进行比较,并选 择保持递增的一个序列,所以总能找到LIS,但是时间复杂度为O(N^2),空间复杂度为O(N): 此解法的性能的瓶颈在于对于位置为i+

一个算法题,又是小明。囧

第一次写博客文章,有点小紧张.若是有什么错误还望众大神指点.为了备战下个月的蓝桥杯,苦战算法题,觉得有一道题不错,就拿来分享一下. 原文如下:地宫取宝,X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签.地宫的入口在左上角,出口在右下角.小明被带到地宫的入口,国王要求他只能向右或向下行走.走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿).当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可

(关于一个算法题的两点新思路)给你一组字符串 如 {5,2,3,2,4,5,1,2,1,5},让你输出里面出现次数最多且数值最大的一个,出现几次

在网上看到一个算法题,不是很难,搜一下也有解决办法,但是一般都是几层for循环,试着写了下 /** * 给你一组字符串 如 {5,2,3,2,4,5,1,2,1,5},让你输出里面出现次数最多且数值最大的一个,出现几次 * 优点:时间复杂度为O(n) * 缺点:产生一些多余的空间,如 6,7,8没有的数也会分配一个数组空间,但是基本可以忽略 * 限制:需要预先知道最大的值是多少,或者说小于多少,这样才好确定预先分配一个数组长度是多少 */ public static void method1()

一道有趣的算法题:仿照Excel的列编号,给定一个数字,输出该列编号字符串

       By Long Luo 最近遇到一个算法题: 仿照Excel的列编号,给出一个数字,输出该列编号字符串. 例如:A对应1,Z对应26,AA对应27,AZ对应52 ...... 这个题目是一个典型的26进制思路去处理,但是这个题目里面有很多陷阱,在1, 26, 52等特殊情况进行考虑,经过晚上接近1个小时的编写,完成的代码如下: C++代码如下: #include <iostream> #include <string.h> using namespace std; /

算法题:给你一个自然数N,求[6, N]之内的全部素数中, 两两之和为偶数的那些偶数。

/* 算法题:给你一个自然数N,求[6, N]之内的全部素数中. 两两之和为偶数的那些偶数. */ #include <iostream> using namespace std; void Grial(int n) { int *b = new int[n]; int k = 0; b[k++] = 2; b[k++] = 3; b[k++] = 5; for (int i = 6; i < n; i++) { int j; for (j = 0; j < (k+1) / 2 ;

牛顿迭代法求解平方根

牛顿迭代法求解平方根 2015-05-16 10:30 2492人阅读 评论(1) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 一个实例 迭代简介 牛顿迭代法 牛顿迭代法简介 简单推导 泰勒公式推导 延伸与应用 一个实例 //java实现的sqrt类和方法 public class sqrt { public static double sqrt(double n) { if (n<0) return Double.NaN; double err = 1e

算法题:复制复杂链表之复制连接法

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 上篇文章算法题:复制复杂链表之空间换时间法我们给出了用映射的方法来为新复制的链表中的每个结点设置any指针,本文给出的是<剑指offer>上给出的算法与代码,<剑指offer>上提到该算法的实现三个步骤:        第一步:复制原始链表的任意结点N并创建新结点N',在把N'连接到N的后面:        第二步:设置每个结点的any指针:        第三步:将长链表分成两个链表,一个是原始链表,另外一个就是我们所要求的复制