86 lines
1.8 KiB
Markdown
86 lines
1.8 KiB
Markdown
|
## 每日一题 - my-sqrt
|
|||
|
|
|||
|
### 信息卡片
|
|||
|
|
|||
|
- 时间:2019-06-21
|
|||
|
- 题目链接:无
|
|||
|
> leetcode 上有一个相似的[题目](https://leetcode.com/problems/sqrtx/)
|
|||
|
- tag:`binary search` `math`
|
|||
|
|
|||
|
### 题目描述
|
|||
|
|
|||
|
```
|
|||
|
要求不用数学库,求 sqrt(2)精确到小数点后 10 位
|
|||
|
```
|
|||
|
|
|||
|
### 参考答案
|
|||
|
|
|||
|
1. 二分法
|
|||
|
|
|||
|
这个解法比较直接,就是普通的二分。
|
|||
|
通过每次取中间值进行比较,我们可以舍去一半的结果。时间复杂度logn
|
|||
|
|
|||
|
参考代码:
|
|||
|
|
|||
|
```js
|
|||
|
function sqrt(num) {
|
|||
|
if (num < 0) return num;
|
|||
|
let start = 0;
|
|||
|
let end = num;
|
|||
|
let mid = num >> 1;
|
|||
|
const DIGIT_COUNT = 10;
|
|||
|
const PRECISION = Math.pow(0.1, DIGIT_COUNT);
|
|||
|
while (Math.abs(+(num - mid * mid).toFixed(DIGIT_COUNT)) > PRECISION) {
|
|||
|
mid = start + (end - start) / 2.0;
|
|||
|
if (mid * mid < num) {
|
|||
|
start = mid;
|
|||
|
} else {
|
|||
|
end = mid;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return mid;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
2. 牛顿迭代法
|
|||
|
|
|||
|
这种方法是牛顿发明的,比较巧妙。
|
|||
|
其实上述问题可以转化为x^2-a = 0,求x的值。其实也就是曲线和y轴交点的横坐标。
|
|||
|
我们可以不断用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。
|
|||
|
|
|||
|
![2019-06-27](../assets/daily/2019-06-27.gif)
|
|||
|
|
|||
|
(图片来自Wikipedia)
|
|||
|
|
|||
|
参考代码:
|
|||
|
|
|||
|
```js
|
|||
|
function sqrtNewton(n) {
|
|||
|
if (n <= 0) return n;
|
|||
|
|
|||
|
let res;
|
|||
|
let last;
|
|||
|
const DIGIT_COUNT = 10;
|
|||
|
const PRECISION = Math.pow(0.1, DIGIT_COUNT);
|
|||
|
|
|||
|
res = n;
|
|||
|
|
|||
|
while (Math.abs(last - res) > PRECISION) {
|
|||
|
last = res;
|
|||
|
res = (res + n / res) / 2;
|
|||
|
}
|
|||
|
|
|||
|
return res;
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 其他优秀解答
|
|||
|
|
|||
|
```
|
|||
|
暂无
|
|||
|
```
|