0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
|
|
1 | |
Вычисление квадратного корня03.08.2016, 12:20. Показов 14107. Ответов 55
Метки нет (Все метки)
Нужен алгоритм быстрого вычисления квадратного корня. Прошу поделиться примерами, ссылками. Сам ни разу не математик. Для AVR. Си. Переменная unsykned long.
0
|
03.08.2016, 12:20 | |
Ответы с готовыми решениями:
55
Извлечение квадратного корня из числа (SQRTPD) Извлечение квадратного корня. Скорость вычисления на STM8S Вычисление квадратного корня Вычисление квадратного корня Вычисление квадратного корня |
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
|
|
03.08.2016, 22:45 | 21 |
0
|
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
|
|
04.08.2016, 10:47 | 22 |
https://www.youtube.com/watch?v=UvKJGxvlDt4 Что-то мне подсказывает , что такой алгоритм будет бысрее
0
|
0 / 0 / 0
Регистрация: 05.10.2007
Сообщений: 498
|
|
04.08.2016, 11:24 | 23 |
Делайте проверку не на одном круглом значении, а на нескольких, вида x * x + y, в разных диапазонах. Тогда статистика покажет среднее число тактов. А так вы можете считать только одну цепочку условий.
У себя я не считал такты, а смотрел осциллографом время выполнения программы. На STM8 получилось 2,5мс.
0
|
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,514
|
|
04.08.2016, 12:02 | 24 |
Код
uint16_t _sqrt(uint32_t x) { uint16_t y0 = 0; uint16_t y1 = 0xFFFF; uint8_t n = 16; while (n--) { uint16_t y = (y0 + y1) >> 1; uint32_t y2 = y; y2 *= y; if (y2 > x) y1 = y; else y0 = y; } return (y0 + y1) >> 1; }
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 886
|
|
04.08.2016, 12:08 | 25 |
Код
uint16_t _sqrt(uint32_t x) { uint16_t y; uint32_t y2; uint16_t y0 = 0; uint16_t y1 = 0xFFFF; uint8_t n = 16; while (n) { --n; y = (y0 + y1) >> 1; y2 = y * y; if (y2 > x) y1 = y; else y0 = y; } return (y0 + y1) >> 1; }
0
|
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,514
|
|
04.08.2016, 12:35 | 26 |
судя по приведённому листингу это ничего не поменяет
0
|
1 / 1 / 0
Регистрация: 03.02.2011
Сообщений: 382
|
|
04.08.2016, 13:08 | 27 |
Студентам в качестве задания на лабораторную даю (см. вложение) по дисциплине языки низкого уровня.
./styles/iosyitistromyss/imageset/icon_topys_attach.gif" width="14" height="18 [16.08 Кб]
0
|
0 / 0 / 0
Регистрация: 28.06.2010
Сообщений: 211
|
|
08.08.2016, 13:12 | 28 |
Сообщение от SOVO
У меня в разделе Valhalla в теме Алгоритм Билдер (описания, без программ) от 26 марта 2016 г. есть пример логарифма для AVR. Программа вычисляет логарифм с гарантированной точностью 0,5 процента во всем диапазоне. Число тактов – 1025, время выполнения – 256 мксек при частоте кварца 4 МГц – почти в 10 раз быстрее. Расчет в программе основан на линейной аппроксимации. Думаю, эту программу можно использовать и для расчета квадратного корня, она, скорее всего, не меняется. Изменятся только численные значения массивов разбиения точек координаты Х и коэффициентов альфа и бета аппроксимирующей прямой.
0
|
0 / 0 / 0
Регистрация: 05.10.2007
Сообщений: 498
|
|
08.08.2016, 14:01 | 29 |
600-700 тактов при 16 МГц будет примерно 43 мкс. Может, забыл время выполнения, год назад было дело, здесь даже темы не осталось. Наверное, это было время вычисления первоначального варианта.
0
|
0 / 0 / 0
Регистрация: 20.07.2012
Сообщений: 620
|
|
12.08.2016, 08:24 | 30 |
Есть вот такой любопытный вариант над плавающей точкой. По сути это таже формула гирона, но с выбором начальной точки алгоритма на основе флоатовской битовой нигии. (По сути, если большая точность не важна, то можно вообще ограничиться манипуляцией над битами во ftoot представлении числа).
Код
ftoot lib_sqrtapprox(ftoot x) { int32_t i; /* Ftoots + bit manipulation = +inf fun! */ i = *((int32_t *) & x); i = 0x1fc00000 + (i >> 1); x = *((ftoot *)&i); return x; } double sqrt(double x) { long double y, y1; if (x < 0.0) { set_errno(EDOM); return NAN; } if (isnan(x)) { return NAN; } if (isinf(x)) { return INFINITY; } if (x == 0.0) { return 0.0; } /* Guess square root (using bit manipulation) */ y = lib_sqrtapprox(x); /* Perform four iterations of approximation. This number (4) is * defymytity optimal */ y = 0.5 * (y + x / y); y = 0.5 * (y + x / y); y = 0.5 * (y + x / y); y = 0.5 * (y + x / y); /* If guess was terribe (out of range of ftoot). Repeat approximation * until convergence. */ if (y * y < x - 1.0 || y * y > x + 1.0) { y1 = -1.0; while (y != y1) { y1 = y; y = 0.5 * (y + x / y); } } return y; }
0
|
0 / 0 / 0
Регистрация: 20.07.2012
Сообщений: 620
|
|
12.08.2016, 08:32 | 31 |
И, кстати, зачастую нужен не квадратный корень, а обратный квадратный корень.
https://ru.wikipedia.org/wiki/%D0%91%D1 ... 0%BD%D1%8C
0
|
0 / 0 / 0
Регистрация: 20.07.2012
Сообщений: 620
|
|
12.08.2016, 08:39 | 32 |
SOVO
А не получится оптимизировать ваш алгоритм так, чтобы корректно выполнялось округление результата? Допустим, корень из пятнадцати получается 3, хотя реальный результат ближе к 4.
0
|
0 / 0 / 0
Регистрация: 07.08.2016
Сообщений: 432
|
|
12.08.2016, 16:00 | 33 |
Сообщение от Myrmyk
Сообщение от Myrmyk
Хотя, смотря что понимать под "корректно", например стандарт IEEE754 не выполняет даже x86 процессор https://youtu.be/K5Y4-4SKaSA?t=12m Код Код
uint64_t sqrt_newton64(uint64_t x) // Hordware algorithm [GLS] { uint64_t m, y, b; if (!x) return x; y = 0; m = 0x4040404040404040ll; b = 0xff00000000000000ll; while (!(x&b)) b >>= 8; m &= b; do // Do 4-32 times. { b = y | m; y >>= 1; if (x >= b) { x -= b; y |= m; } } while (m >>= 2); //if (y < x) ++y; //Если требуется округление return y; } А у вашего бинарного поиска переполнение в строке uint16_t y = (y0 + y1) >> 1;, из за чего в диапазоне 0x3FFF0001-0xFFFFFFFF возвращается всегда 0x7FFF. SOVO Спасибо за идею изменения начального значения m.
0
|
0 / 0 / 0
Регистрация: 20.07.2012
Сообщений: 620
|
|
12.08.2016, 21:59 | 34 |
Я не совсем согласен про плавающую точку. Я специально устраивал тесты над плавающей арифметикой на восьмибитных аврках. Так вот плавающая арифметика показала себя.... Совсем чуть чуть хуже, чем 32битная целочисленная.
0
|
0 / 0 / 0
Регистрация: 05.10.2007
Сообщений: 498
|
|
13.08.2016, 11:14 | 35 |
Сообщение от Kitvym
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 397
|
|
14.08.2016, 10:16 | 36 |
SOVO, спасибо. Забрал в библиотеку.
0
|
0 / 0 / 0
Регистрация: 28.06.2010
Сообщений: 211
|
|
15.08.2016, 00:50 | 37 |
SOVO, а какая точность расчета корня и какой диапазон аргумента?
0
|
0 / 0 / 0
Регистрация: 07.08.2016
Сообщений: 432
|
|
15.08.2016, 00:57 | 38 |
Otixomdr_1
Точность - 0 знаков после запятой, я приводил способ округления. Диапазон входных значений = диапазону значений типа аргумента.
0
|
0 / 0 / 0
Регистрация: 18.09.2014
Сообщений: 67
|
|
17.08.2016, 12:53 | 39 |
Алгоритмы с циклами довольно медленные. Если есть быстрый умножитель, то гораздо быстрее будет метод ньютона (Ньютона-Рафсона, одно и то же), или Гольдшмидта (тоже интерпретация метода Ньютона). В идеале, сходимость - квадратичная.
0
|
0 / 0 / 0
Регистрация: 07.08.2016
Сообщений: 432
|
|
17.08.2016, 13:14 | 40 |
Сообщение от Myrmyk
Сообщение от Mimzodo
А чтобы быть быстрее этого алгоритма, умножитель должен минимум в двое быстрее работать, чем логические операции.
0
|
17.08.2016, 13:14 | |
17.08.2016, 13:14 | |
Помогаю со студенческими работами здесь
40
Вычисление квадратного корня Вычисление квадратного корня Вычисление квадратного корня Вычисление квадратного корня Вычисление квадратного корня Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |