我正在使用以下公式实现Babylonian方法来近似数字n
的平方根:
nextGuess = (lastGuess + n / lastGuess) / 2;
因此,当nextGuess
和lasGuess
几乎相同时,nextGuess
是近似的平方根。
正在做的是检查nextGuess
和lastGuess
是否小于非常小的数字,例如0.0001
,那么我可以声称nextGuess
是n
的近似平方根{1}}。如果不是nextGuess
成为lastGuess
。
那我怎么能以正确的方式实现呢?
我目前的代码:
public static void getApproximatedSquare(long n){
DecimalFormat decimalFormat = new DecimalFormat("#.####");
decimalFormat.setRoundingMode(RoundingMode.CEILING);
double lastGuess = 1, nextGuess;
nextGuess = (lastGuess + n / lastGuess) / 2;
Double init = 0.0001;
System.out.println(decimalFormat.format(init));
if (Double.valueOf(decimalFormat.format(nextGuess)) <= init)
//todo
}
答案 0 :(得分:4)
目前的实施草案存在一些缺陷:
Double.valueOf(decimalFormat.format(...))
,它只是从结果中删除了一些精度nextGuess < init
,而是difference_between_nextGuess_and_lastGuess < init
if
。您需要for
或while
或(在我的解决方案中)do... while
这应该有效(在每一步,它打印上一次和下一次猜测)
public static double getApproximatedSquare(long n) {
DecimalFormat decimalFormat = new DecimalFormat("#.####");
decimalFormat.setRoundingMode(RoundingMode.CEILING);
double lastGuess, nextGuess = 1;
double init = 0.0001;
do {
lastGuess = nextGuess;
nextGuess = (lastGuess + (double) n / lastGuess) / 2;
System.out.println(decimalFormat.format(lastGuess)+" ---> "+decimalFormat.format(nextGuess));
} while (Math.abs(lastGuess - nextGuess) >= init);
return nextGuess;
}
答案 1 :(得分:1)
使用绝对容差总是一个坏主意,因为它没有考虑参数的数量级。相对误差更好。
但是在平方根的情况下,我建议采用更好的方法:确保初始近似值在精确根的√2倍内。这是通过在参数的浮点表示中将指数2减半而获得的。 (如果你不能访问这个指数,你可以通过连续的除法或乘法来获得它,直到达到[1,2]的间隔。)
示例:对于27,您有16≤27<那么1≤√27/ 4&lt; √2,你可以从4开始迭代。
然后执行巴比伦公式的四次迭代。不能少,不多了。
在该示例中,经过四次迭代后,您将获得5.19615242271,这是完全正确的。
如果你感觉连续的减半或加倍过程很慢并且认为牛顿更快,那么考虑(x + n / x)/ 2&gt; x / 2,因此牛顿实际上收敛慢于减半并涉及更多算术 !
答案 2 :(得分:0)
如果nextGuess
的值100%肯定会降低并达到足够好的值,那么你不能这样做吗?
public static void getApproximatedSquare(long n){
DecimalFormat decimalFormat = new DecimalFormat("#.####");
decimalFormat.setRoundingMode(RoundingMode.CEILING);
double lastGuess = n + 1;
double nextGuess = n;
double init = 0.0001;
while (lastGuess - nextGuess > init)
{
lastGuess = nextGuess;
nextGuess = (lastGuess + n / lastGuess) / 2;
}
System.out.println(decimalFormat.format(init));
}
答案 3 :(得分:-1)
当nextGuess
从上面接近sqrt(n)
时,您可以使用:
double lastGuess = n;
double nextGuess = n;
double epsilon = 1e-4;
while (lastGuess - nextGuess > epsilon) {
lastGuess = nextGuess;
nextGuess = (lastGuess + n / lastGuess) / 2;
}