http://introcs.cs.princeton.edu/java/13flow/Sqrt.java.html:
public class Sqrt {
public static void main(String[] args) {
// read in the command-line argument
double c = Double.parseDouble(args[0]);
double epsilon = 1e-15; // relative error tolerance
double t = c; // estimate of the square root of c
// repeatedly apply Newton update step until desired precision is achieved
while (Math.abs(t - c/t) > epsilon*t) {
t = (c/t + t) / 2.0;
}
// print out the estimate of the square root of c
System.out.println(t);
}
}
事情就是......我完全理解程序是如何运作的。我遇到的问题是方程式f(x)= x ^ 2 - c以及它与上述代码的关系。比如,为什么要用x除以x(x-c / x)?对于这些例子中的一些,似乎缺少数学解释。换句话说,我正在寻找一个简单的数学观点的解释,而不是编码那么多。
答案 0 :(得分:4)
您获得c
并且想要解决
t = sqrt(c)
或等效,
c = t^2
或者再一次,
c - t^2 = 0.
我将调用上面的等式f(t) = 0
(不提及c
,因为它是给定的常量)。
牛顿方法迭代t
的试用值,我将其标记为t_i, t_{i+1}, ...
。
泰勒扩展到第一顺序是:
f(t_i + dt_i) = f(t_i) + dt_i * f'(t_i) + ...
因此,如果您没有f(t_i) = 0
,则添加dt_i
以便
f(t_i + dt_i) nearly = 0 = f(t_i) + dt_i * f'(t_i) + ...
所以dt_i = -f(t_i) / f'(t_i)
,即f(t_i + -f(t_i) / f'(t_i))
比f(t_i)
更接近于零。
如果您为f(t) = c - t^2
执行导数,您会发现代码t_{i+1} = (c / t_i + t_i) / 2
中的等式只是迭代公式t_{i+1} = t_i + dt_i
,其中dt_i
估算在上面。
这是迭代方法,因此它没有提供精确的解决方案。您需要决定何时停止(足够的精度),否则算法将永远持续下去。这就是您检查f(t_i) < threshold
而不是真f(t_i) = 0
的原因。在他们的案例中,他们选择了threshold = epsilon * t^2
;我认为使用t^2
的乘法因为如果你使用固定常数作为阈值,你可能会遇到数值精度问题(即如果你正在玩万亿,你永远不会得到{{1的固定精度由于浮点表示的有限精度。)
答案 1 :(得分:1)
基于code,已经在Javadoc评论中解释了以下内容:
* Computes the square root of a nonnegative number c using
* Newton's method:
* - initialize t = c
* - replace t with the average of c/t and t
* - repeat until desired accuracy reached
答案 2 :(得分:1)
好的,我会给它一个bash(参见内联评论):
public class Sqrt {
public static void main(String[] args) {
// read in the command-line argument (i.e. this is the value that we want
// square root from.)
double c = Double.parseDouble(args[0]);
// Since the the square root of non-squares are irrational, we need some
// error tolerance. In other words, if the answer is less than epsilon wrong
// we'll take it.
double epsilon = 1e-15; // relative error tolerance
// t is our first guess (c / 2.0 works well too - in fact it tends to be
// better.)
double t = c; // estimate of the square root of c
// repeatedly apply Newton update step until desired precision is achieved
// The condition here is rather elegant and optimized... to see why it works,
// simply break it up. The absolute is there to cater for negative values, but
// for c >= 0:
// | c - c/t | > epsilon * t
// t * ( t - c / t ) > epsilon
// tt - c = > epsilon)
while (Math.abs(t - c/t) > epsilon*t) {
// Improve the guess by applying Newton's genius :-)
// Take the original number, divide by the guess add t and take the
// average.
t = ( c / t + t) / 2.0;
}
// print out the estimate of the square root of c
System.out.println(t);
}
}
答案 3 :(得分:0)
ejlab.net jelmar
我相信上面提到的代码来自R.Sedgewick的书“Java编程简介”,第62页。他在本书中试图说明你可以使用f(x)=x^2-c
作为一个特例来查找任何正数的平方根。它是如何工作的:
牛顿的方法陈述X(n+1)=X(n)-(F(X(n))/F'(X(n)))
。假设在F(X)=X^2-C
中C=2
,因为我们正在寻找2的平方根(如果你想找到36的平方根,那么C=36
等)。然后函数F(X)
的一阶导数是F'(X)=2X
。应用牛顿方法得到
X(n+1)=X(n)-((X^2-C)/(2X))
X(0)=2
的
n=1,
X(1)=2-(2^2-2)/(2*2)
&gt; X(1)=1.5
;
n=2
X(2)=1.5 -(1.5^2-2)/(2*1.5)
&gt; X(2)=1.41666667
等等...