Pull to refresh

Comments 25

Эх, думал тут будет обзор алгоритмов, а тут даже не Ньютон (и уж тем более не Ньютон для обратного корня).
Может проще открыть учебник по численным методам?

Мой опыт говорит, что любые хитропопые методы заходят куда лучше, после того, как сам решил задачу ужасающим методом. Вот тогда их хитропопость начинает выглядеть как cleverness. А если начинать с них, то (без понимания масштаба задачи), оно выглядит как "ЗАЧЕМ ЭТО ВСЁ КАКОЙ УЖАС".

любые хитропопые методы заходят куда лучше, после того, как сам решил задачу ужасающим методом
Это все абсолютно верно. Но после «сам решил» даже вы не подразумеваете, что на этом нужно останавливаться. А здесь то какой вообще был резон для написания статьи? Ну, решил ты «ужасающим методом», допустим. Проведи тогда хотя бы анализ решения, изучи его сходимость, проверь случая расхождения, поиграйся с оптимизацией, сравни с другими решениями — это все необходимо, чтобы твой опыт действительно стал полезным для других. Но здесь ничего этого и близко нет. Увы, пусть это и мои трудности, но лично я вижу только «не знаю и горжусь этим».

Это называется негативный перфекционизм, и с ним лучше бороться.

Речь шла как раз об отсутствии здорового желания саморазвиваться (положительного перфекционизма), без которого все превращается, уж прошу извинить меня за мой французский, в «смотрите как красиво я пукнул». Решил сам — молодец, правильный подход, если только это является лишь первым шагом, а не последним.

Негативным перфеционизмом является как раз обратное — это когда человеку, который первый раз в жизни что-то сделал приходит кто-то и говорит "ну куда ты со своим рылом в калашный ряд лезешь-то? Вот если бы ты поднапрягся, саморазвился, да показал бы что-то, достойное Старых Мастеров (гигантов, на чьих плечах покоится И. Ньютон), вот тогда да, а так-то ты, куда лезешь-то?".


Негативный перфекнционизм — одна из характерных черт русской культуры, требующей либо восхитить, либо устыдиться.

ну куда ты со своим рылом в калашный ряд лезешь-то

Меня удивляет, что вы смогли увидеть такой подтекст в моих словах о том, что: «Решил сам — молодец, правильный подход, если только это является лишь первым шагом, а не последним.»

По факту вы сейчас пытаетесь найти в моей фразе контекст, которого в ней нет, но который беспокоит вас лично.
Корень — это слишком просто. Посчитайте, например, гамма-функцию — её как раз и в стандартных библиотеках обычно нет.
Интересное предложение! Постараюсь сделать и написать простым языком как такое можно запрограммировать :)
И категорически вредно всегда пользоваться всем готовым, не имея никакого представления о внутреннем устройстве.
Меня несколько смущает следующий вопрос — неужели вы никогда не слышали про итерационную формулу Герона? Было бы весьма похвально додуматься до нее самостоятельно какому-нибудь школьнику или первокурснику, но для профильного выпускника, который прослушал курс лекций по численным методам и вычислительной математике (и, по идее, заведомо перепробовал все эти алгоритмы задолго до окончания обучения), не знать подобных базовых вещей по меньшей мере странно. К сожалению, здесь это выглядит как бравирование собственным незнанием: «Не знаю и знать не хочу».

Логарифмическая сложность алгоритма? Или другая? :)
Алгоритм имеет квадратичную сходимость, как и метод Ньютона, из которого он вытекает.

Кстати, какие возможности ускорения этого алгоритма можно реализовать на ваш взгляд?
Основные правила по поиску возможностей таковы:
1. Подумать самостоятельно (для затравки)
2. Изучить имеющуюся базу/существующие решения
3. Подумать еще раз (о том, как сделать лучше)
4. Верифицировать идею
5. Если результаты неоптимальны, вернуться в пункт 1 и повторить цикл.

У вас здесь, к сожалению, в наличии только шаг 1, шаги 2-5 пропущены, иначе бы вы обнаружили, что одним из известных методов для улучшения выбранного вами метода является прескейлинг. Но лучше все же было бы заведомо исходить из того, что постоянное самообразование является строгой необходимостью для специалиста — меня удивляет, почему нынешняя молодежь не то что книги и учебники не читает, но даже затрудняется прогуляться до гугла и английской википедии, где описано весьма впечатляющее для затравочных размышлений количество методов вычисления корня.
Поздравляю, вы изобрели велосипед. Могу понять вашу личную радость открытия, но для прочих учебник по численным методам будет полезнее, потому ценность статьи приблизительно равна нулю.
у этого алгоритма слишком простая конструкция, чтобы называть его таким чудом инженерной мысли, как велосипед
Чудо инженерной мысли — не в сложности, а в простоте. Велосипед, кстати, тоже отнюдь не сложен.
UFO just landed and posted this here

6 знаков после запятой забыли. 1000*1000000 — уже миллиард.

UFO just landed and posted this here
UFO just landed and posted this here

Как ни странно, почти хорошо.
Радикальное улучшение будет, если root = 0.5 * ( rn + root); заменить на root = rn / n + root * (1.0 - 1.0 / n); — тогда будет чистый метод Ньютона. Отсюда видно, почему 0.5 для квадратного корня.
По мелочи — 1/rootn можно вычислить за логарифмическое число операций.
И "пять знаков после запятой" чаще интерпретируется как |root/rn — 1| < 10-5, а не как |rootn — rn| < 10-5, иначе для чисел порядка 10-6 будет получаться полная чушь.

вообще, идея поиска корня довольна простая:
пусть f(x) = x^^n=Y
Err= f(x0)-Y
dErr/dx = n*x^^(n-1)
dx = ( Y-f(x0) )/( n*x^^(n-1) )
x1= x0 + (Y — x0^^n )/(n*x0^^(n-1)) ==>
x1 = x0*(1-1/n) + (1/n)*Y / x0^^(n-1);
собственно, Ваш алгоритм для корня третьей степени отличается от приведенного мной тем, что он «Ваш» (первое) (а мой- Ньютона :-)),
константа 0,5 //root = 0.5 * ( rn + root);// не самая оптимальная в плане сходимости (второе), и вместо деления в цикле лучше использовать умножение, оно считается быстрее, а для корней большой степени его еще и можно ускорить (x^^7 = x*x^^2*(x^^2)^^2, вместо шести умножений- 2 умножения и два(!) возведения в квадрат, для x^^32 ускорение еще приятнее :-)) ( это третье)

double r_n1;
while(mabs(root — rn) >= eps){
r_n1 = 1.0;
for(int i = 1; i < rootDegree; i++){
r_n1 = r_n1 *root;
}
rn = root;
root = rn*(1.0 — 1/rootDegree) + (1.0/rootDegree) *num / r_n1;
countiter++;
}

П.С. а для квадратного корня Вы изобрели формулу Герона. ну как изобрели- Вам ее в школе рассказали, потом Вы ее забыли, а потом- изобрели. «честно нашел».
уже алгоритм для квадратного корня не работает для чисел строго меньше 4. например корень из 2 = 1 :) так как условие root — num / root > eps немного некорректно в этом случае.
Спасибо всем комментаторам за критику! Буду писать подробнее, проще и рассматривать больше интересных тем :)

Почему бы не рассмотреть более общую задачу: нахождение x^p для произвольной вещественной степени p?

Sign up to leave a comment.

Articles