開根 sqrt(int v, double t)

/**
 * 實現一個函數, 完成 開根號 的操作, 方法簽名如下.
 * 
 * double sqrt(int v, double t)
 * <p>
 * 要求:
 * 
 * 不能調用系統庫函數, 諸如 Math.sqrt(v) 之類的; 假設計算出的結果為 r, 要求滿足如下條件, , 其中 是真實的值, t 為給定的一個誤差范圍, 例如0.1等, 即你計算出的值要在給定的誤差范圍內. 實現語言不限,
 * 你條件可以比上述更加苛刻, 但不能寬松, 舉例而言, 我調用你的接口 sqrt(9, 0.21) 返回值屬于 [2.79, 3.21] 這個區間的任意一個都滿足條件.
 * </p>
 * 
 */
public class SqrtDemo {

    // 窮舉法
    private static double sqrt1(int v, double t) {
        double result = 0;
        Long start = new Date().getTime();

        while (true) {
            if ((result + t) * (result + t) >= Math.abs(v - t)) {
                Long end = new Date().getTime();
                System.out.println("自寫爆菊耗時:" + (end - start) + "ms");
                return result;
            }
            result += t;// 適當分段
        }
    }

    // 二分法
    private static double sqrt2(int v, double t) {
        Long start = new Date().getTime();
        double value = v / 2;
        double low = 0, up = v;

        while (Math.abs(up - value * value) > t) {
            if (value * value > v) {
                low = 0;
                up = value;
            } else if (value * value < v) {
                low = value;
            }
            if (value == (low + up) / 2)
                break;
            value = (low + up) / 2;
        }
        Long end = new Date().getTime();
        System.out.println("自寫二分耗時:" + (end - start) + "ms");
        return value;
    }

    // !!牛頓快速迭代法
    // 求出根號a的近似值:首先隨便猜一個近似值x,然后不斷令x等于x和a/x的平均數,迭代個六七次后x的值就已經相當精確了。
    // 不斷用(x,f(x))的切線來逼近方程x^2-a=0的根。根號a實際上就是x^2-a=0的一個正實根,這個函數的導數是2x。
    // 也就是說,函數上任一點(x,f(x))處的切線斜率是2x。那么,x-f(x)/(2x)就是一個比x更接近的近似值。
    // 代入f(x)=x^2-a得到x-(x^2-a)/(2x),也就是(x+a/x)/2。
    private static double sqrt3(int v, double t) {
        double result = 0, value = v;
        Long start = new Date().getTime();
        while (true) {
            result = value;
            value = (value + v / value) / 2;
            if (Math.abs(result - value) <= t) {
                Long end = new Date().getTime();
                System.out.println("自寫牛頓耗時:" + (end - start) + "ms");
                break;
            }
        }
        return result;
    }


    public static void main(String[] args) {
        System.out.println(sqrt1(1000000000, 0.00001));
        System.out.println(sqrt2(1000000000, 0.00000001));
        System.out.println(sqrt3(1000000000, 0.00000001));

        Long start = new Date().getTime();
        Math.sqrt(10000000);
        Long end = new Date().getTime();
        System.out.println("系統sqrt耗時:" + (start - end) + "ms");
        System.out.println(Math.sqrt(1000000000));
    }
}


自寫爆菊耗時:5530ms
31622.776601556234
自寫二分耗時:0ms
31622.776601683792
自寫牛頓耗時:0ms
31622.776601684047
系統sqrt耗時:0ms
31622.776601683792
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 原文:http://blog.sina.com.cn/s/blog_4b9eab320100sdex.html 這...
    小人國國王閱讀 4,601評論 0 1
  • 實現該函數需要重點考慮以下兩方面問題: 時間復雜度乘法的開銷相對較大,所以在這個問題上,我們可以將時間復雜度等同于...
    yuansip閱讀 1,173評論 0 0
  • ![圖片上傳中…42%](file:///private/var/mobile/Containers/Data/A...
    影子倒了閱讀 788評論 12 22
  • “你還好嗎”?每當有人這樣問到的時候,總會情不自禁的回答:我很好。 真的好嗎?輕描淡寫的一句話 帶過了一段煎熬的時光…
    半夏傾閱讀 241評論 0 1
  • 蓮 去給后輩在酒吧助演的那天晚上,我凌晨一點才到家。 在門口被自己壽司店里的客人攔住之后,看當時的情形,怕是一時半...
    夜清和閱讀 653評論 0 1