Я реализую в java метод Babylonian/Heron для получения квадратного корня числа на основе Информация из Википедии
В настоящее время у меня есть:
public static void main(String[] args) {
System.out.println(Sqrt.sqrt1(8));
//System.out.println(Sqrt.sqrt2(8)); //Infinite loop
System.out.println(Sqrt.sqrt3(8));
System.out.println(Sqrt.sqrt4(8));
}
static float sqrt1(float x) {
float b = 0, h = x;
while (b != h) {
b = (h + b) / 2;
h = x / b;
}
return b;
}
static double sqrt2(double x) {
double b = x, h = 0;
while (b != h) {
b = (h + b) / 2;
h = x / b;
}
return b;
}
static double sqrt3(double x) {
double b = x, h = 0;
while (Math.abs(b - h) > 0.000000000001) {
b = (h + b) / 2;
h = x / b;
}
return b;
}
static double sqrt4(double x) {
double r = x, t = 0;
while (t != r) {
t = r;
r = (x / r + r) / 2;
}
return r;
}
Результат будет:
2.828427
2.82842712474619
2.82842712474619
Метод sqrt2 будет зацикливаться бесконечно, но это происходит только с числами типа double, потому что метод sqrt1 отлично работает с числами с плавающей запятой. Я не знаю, почему это. Таким образом, метод sqrt3 выглядит как способ, если я хочу работать с двойными значениями.
Я немного запутался в том, какие методы я реализую. «Вавилонский метод такой же, как метод Герона?».
Насколько я понимаю, вавилонский метод основан на том факте, что сторона квадрата представляет собой квадратный корень из площади квадрата (x). Таким образом, вы можете начать с прямоугольника с размерами b.h, получить среднее значение двух сторон (b=b+h/2), а затем рассмотреть этот результат как сторону меньшего прямоугольника и, конечно же, получить другую сторону (h=x /б). Прямоугольник начнет приближаться к нужному квадрату. Вот что я сделал в методах sqrt1, sqrt2 и sqrt3:
while (b != h) {
b = (h + b) / 2;
h = x / b;
}
С другой стороны, ссылка в Википедии говорит, что метод вавилонян / цапель такой же, и описывает его как:
«Основная идея заключается в том, что если x является завышенной оценкой квадратного корня из неотрицательного действительного числа S, то S/x будет заниженной оценкой, и поэтому можно разумно ожидать, что среднее значение этих двух чисел обеспечит лучшее приближение».
Вы можете увидеть эту реализацию в методе sqrt4:
while (t != r) {
t = r;
r = (x/r + r) / 2;
}
Из того, что я вижу, эти два метода не одинаковы, но похожи. Пожалуйста, поправьте меня, если я ошибаюсь.
Что-то интересное, что я не могу сделать: while (b != h) {
когда b и h удваиваются, как показано в методе sqrt2, потому что он будет зацикливаться навсегда. Вместо этого я использовал while (Math.abs(b - h) > 0.000000000001) {
Однако я могу сделать: while (t != r) {
с b и h удваивается, как показано в sqrt4.
Я был бы признателен, если бы кто-нибудь объяснил это поведение.
----------- РЕДАКТИРОВАТЬ:---------------------------------- --------------------------
Как и предполагалось, оба алгоритма одинаковы, но реализованы по-разному. Однако следующие предлагаемые циклы кода всегда повторяются, как sqrt2 с x = 8:
static double sqrt5(double x) {
double b = x;
while (b != x/b) {
b = (x / b + b) / 2;
}
return b;
}
Итак... в чем отличие sqrt4 от других реализаций? Почему он не зацикливается навсегда, как другие?