<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Быстрое вычисление квадратного корня на Си</title>
		<description>Discuss Быстрое вычисление квадратного корня на Си</description>
		<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html</link>
		<lastBuildDate>Tue, 14 Apr 2026 19:10:49 +0000</lastBuildDate>
		<generator>JComments</generator>
		<atom:link href="https://chipenable.ru/index.php/component/jcomments/feed/com_k2/144.html" rel="self" type="application/rss+xml" />
		<item>
			<title>nebelwerfer says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-5000</link>
			<description><![CDATA[А что за магическое число: m = 0x4000;? Это половина от максимума int ? А вот 2й вариант работает отлично, спасибо! Мне нужно считать корни из больших чисел до 250 000 000, поэтому увеличил количество: x = (a/x + x)>>1; до 7 и точность приемлима.]]></description>
			<dc:creator>nebelwerfer</dc:creator>
			<pubDate>Sun, 22 Jan 2017 14:19:42 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-5000</guid>
		</item>
		<item>
			<title>Петгосян says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4952</link>
			<description><![CDATA[Если умножение делается за один такт, можно сделать вычисление корня побитовым подбором. На первой итерации выставляем 16 бит в 1, возводим в квадрат, сравниваем с входным числом. Если больше, сбрасываем бит. Потом с 15 битом повторяем то же самое и т.д. Как в АЦП.]]></description>
			<dc:creator>Петгосян</dc:creator>
			<pubDate>Sun, 20 Nov 2016 13:38:09 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4952</guid>
		</item>
		<item>
			<title>Петгосян says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4951</link>
			<description><![CDATA[У функции корня есть некоторые свойства симметрии, которые позволяют вычислять ее только на некотором отрезке, а потом решение распространить на всю ось. Например, sqrt(a*2^16)=2^ 8*sqrt(a). Удобно в качестве такого отрезка взять значения [2^30-2^31), потому что остальные значения можно свести к нему побитовым сдвигом и при этом не будет происходить потеря точности. Сначала вычисляем первый значащий бит (программно половинным делением или процессорной инструкцией, например на ARM это __clz). Потом сдвигаем входное число на это кличество бит и вычисляем корень, полученное значение сдвигаем обратно на в два раза меньшее количество). Для вычисления корня на отрезке интерполируем его многочленом Лагранжа (параболой). Например, возьмем в качестве точек многочлена 2^30, 1,5 * 2^30, 2^31. Можно воспользоваться сторонним сервисом, и не возиться с вычислением коэффициентов. У меня получилась такая формула: -x^2/4991002184 44523 + x/52370 + 14575 Очевидно, напрямую её использовать нельзя, потому что значения не влазят даже в диапазон целых. Но надо учесть, что нам важны только 16 бит результата, поэтому можно немного схитрить и вынести что-то за скобки. (-x/9530269590 + 1) * x/52370 + 14575 (-x/145420 + 65536) * (x/65536) / 52370 + 14575 Ну и последнее - заменить деление на умножение. Допустим, у нас в резерве 30 бит числа. Мы хотим поделить некое число x, например, на 543. Вычисляем, в числе 543 есть 10 бит, в х 16 бит. x / 543 * 2^26 / 2^26 x * (2^26 / 543) / 2^26 x * 123589 / 2^26 Теперь эти знания применяем к своему многочлену. (-x/2^14 * 7384 / 2^16 + 2^16) * (x/2^16) / 2^16 * 20503 / 2^14 + 14575 Не ручаюсь за правильность коэффициентов, надо внимательно проверить. Когда писал, не учел одну штуку, число бит может быть нечетным, отрезок надо брать больше. Естественно, алгоритм будет быстро работать при наличии аппаратного умножения.]]></description>
			<dc:creator>Петгосян</dc:creator>
			<pubDate>Sun, 20 Nov 2016 13:37:26 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4951</guid>
		</item>
		<item>
			<title>Neptun says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4780</link>
			<description><![CDATA[тоже самое но с типом long unsigned long isqrt(unsigned long x) { unsigned long m, y, b; m = 0x4000; y = 0; while (m != 0) { b = y | m; y = y >> 1; if (x >= b) { x = x - b; y = y | m; } m = m >> 2; } return y; }]]></description>
			<dc:creator>Neptun</dc:creator>
			<pubDate>Thu, 07 Apr 2016 15:49:50 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4780</guid>
		</item>
		<item>
			<title>spkik says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4779</link>
			<description><![CDATA[ подскажите пожалуйста как проделать это с переменной типа long?]]></description>
			<dc:creator>spkik</dc:creator>
			<pubDate>Thu, 07 Apr 2016 13:27:55 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4779</guid>
		</item>
		<item>
			<title>spkik says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4778</link>
			<description><![CDATA[ подскажите пожалуйста как проделать это с переменной типа long?]]></description>
			<dc:creator>spkik</dc:creator>
			<pubDate>Thu, 07 Apr 2016 13:25:31 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4778</guid>
		</item>
		<item>
			<title>Васьок says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4308</link>
			<description><![CDATA[Пользовался детским алгоритмом, на мой взгляд достаточно быстр и достаточно компактный. Идея в том что от числа последовательно отнимаются все нечётные числа, и сколько вычитаний удалось сделать, таков и корень числа. Пример, число 49; 1) 49 - 1 = 48 2) 48 - 3 = 45 3) 45 - 5 = 40 4) 40 - 7 = 33 5) 33 - 9 = 24 6) 24 - 11 = 13 7) 13 - 13 = 0 7 циклов, корень числа 49 - 7. И кстати при работе с МК типа AVR-ки лучше избегать делений, т.к. у AVR ядра нет аппаратного деления, а программное занимает дофига тактов. Другое дело ARM Cortex-M3 и выше, у которых деление выполняется за 2... 12 тактов.]]></description>
			<dc:creator>Васьок</dc:creator>
			<pubDate>Thu, 09 Oct 2014 12:34:37 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-4308</guid>
		</item>
		<item>
			<title>Pashgan says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2426</link>
			<description><![CDATA[У меня в IAR` получилось 52 байта, 180 тактов при LOW оптимизации по размеру кода]]></description>
			<dc:creator>Pashgan</dc:creator>
			<pubDate>Fri, 18 Jan 2013 11:33:24 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2426</guid>
		</item>
		<item>
			<title>Pashgan says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2425</link>
			<description><![CDATA[Для IAR`a . Нужно включить опцию создания листинга программы. Project > Options > C/C++ Compiler > List галочка Output list file. Если включить еще и Assembler mnemonics в lst файле будет ассемблерный код, сгенерированный компилятором из твоей программы. Эта информация полезна для оптимизации сишного кода, конечно, если ты знаешь ассемблер. Затем запускаешь компиляцию проекта и с левой стороны (в окне отображения структуры проекта) ищешь файлы с расширением *.lst Они будут созданы для каждого программного модуля. В конце этого файла есть табличка со списком функций и значениями занимаемой памяти. Чтобы прикинуть скорость выполнения какого-нибудь куска кода (обычно функции), я прогоняю этот код в программном симуляторе IAR`a. Включаю опцию Project > Options > Linker > Debug Information ... Запускаю компиляцию и отладку с помощью кнопки Debug (Ctrl+D). Устанавливаю брейкпоинты, открываю окно с регистрами микроконтроллер а (меню View > Register) и запускаю код на выполнение по шагам (F11) или непрерывно (f5). В окне регистров в разделе CPU Register есть строка CYCLES. Она отображает число прошедших тактов. По показаниям этого числа можно прикинуть сколько тактов занимает выполнение функции. То же самое можно делать и в AVR Studio. Там это даже лучше получается, потому что студия моделирует прерывания, а IAR нет.]]></description>
			<dc:creator>Pashgan</dc:creator>
			<pubDate>Fri, 18 Jan 2013 11:19:07 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2425</guid>
		</item>
		<item>
			<title>Neptun says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2424</link>
			<description><![CDATA[Код которий тестировал: #include unsigned int value = 0; unsigned int isqrt(unsigned int x) {	unsigned int m, y, b;	m = 0x4000;	y = 0;	while (m != 0)	{	b = y | m;	y = y >> 1;	if (x >= b)	{	x = x - b;	y = y | m;	}	m = m >> 2;	}	return y; } int main(void) {	asm("nop");	v alue = isqrt(4096);	as m("nop");	while (1); }]]></description>
			<dc:creator>Neptun</dc:creator>
			<pubDate>Fri, 18 Jan 2013 11:07:16 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2424</guid>
		</item>
		<item>
			<title>Neptun says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2423</link>
			<description><![CDATA[ F = 8 MHz, ATmega8, optimization O0 (none): размер 14 байт. скорость 540 циклов - 67.5uS F = 8 MHz, ATmega8, optimization Os (none): размер 14 байт. скорость 2 циклf - 0.25uS]]></description>
			<dc:creator>Neptun</dc:creator>
			<pubDate>Fri, 18 Jan 2013 11:04:52 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2423</guid>
		</item>
		<item>
			<title>Nobody says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2420</link>
			<description><![CDATA[У меня нет компилятора для AVR под рукой. Можете проверить функцию:
unsign ed int isqrt(unsigned int x)
{ unsigned int m, y, b; m = 0x4000; y = 0; while (m != 0) { b = y | m; y = y >> 1; if (x >= b) { x = x - b; y = y | m; } m = m >> 2; } return y;
} Сколько занимает и как долго выполняется?]]></description>
			<dc:creator>Nobody</dc:creator>
			<pubDate>Fri, 18 Jan 2013 09:44:31 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2420</guid>
		</item>
		<item>
			<title>Neptun says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2419</link>
			<description><![CDATA[Напишу как делаеться в AVR Studio. Пишеться код - компилим,смотри м сколько занял,добавляем функцию - и смотрим новий размер кода. Разница между новым и старым значение есть размер функции. Для скорости выполнения. ставим брейкпойнт перед вызовом функции и после,запускаем симуляцию - обнуляем cycle counter,запуска ем симуляцию - и новое значение будеть скоростью выполнения (также можно увидеть сколько время исполняеться функция в мкс или мс).]]></description>
			<dc:creator>Neptun</dc:creator>
			<pubDate>Fri, 18 Jan 2013 09:37:54 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2419</guid>
		</item>
		<item>
			<title>Nikolay says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2418</link>
			<description><![CDATA[Добрый день. Уважаемый, Pashgan, вот ви пишете Можете рассказать как вы определяете сколько занимает и сколько циклов выполняется код?]]></description>
			<dc:creator>Nikolay</dc:creator>
			<pubDate>Fri, 18 Jan 2013 07:43:48 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2418</guid>
		</item>
		<item>
			<title>Pashgan says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2417</link>
			<description><![CDATA[Если написать код так
unsigned int root(unsigned int a)
{ unsigned int x; x = (a/0x3f + 0x3f)>>1; x = (a/x + x)>>1; x = (a/x + x)>>1; return(x);
} получаются точно такие же результаты. Как по ответам, так и по скорости исполнения кода. А по объему даже небольшой выигрыш. Зачем надо было так мудрить?]]></description>
			<dc:creator>Pashgan</dc:creator>
			<pubDate>Fri, 18 Jan 2013 07:01:52 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2417</guid>
		</item>
		<item>
			<title>Pashgan says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2416</link>
			<description><![CDATA[Да нет, все правильно. В википедии приведена формула Герона. Xn+1 = (Xn + A/Xn)*1/2 A - число из которого требуется вычислить корень, X1 - любое положительное число.]]></description>
			<dc:creator>Pashgan</dc:creator>
			<pubDate>Fri, 18 Jan 2013 06:40:34 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2416</guid>
		</item>
		<item>
			<title>Nobody says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2412</link>
			<description><![CDATA[Хотя, я был не прав. По итерационной формуле Герона нужно 8 делений для получения приближенного ответа. В описанном вами методе можно увеличить точность добавив ещё одну итерацию: x = b/x; a = x = (x+a)>>1; Но для AVR, данный алгоритм не оптимальный, т.к. деление выполняется долго. Посмотрите на метод бинарного поиска целочисленного квадратного корня (только умножение и сложение), описан в книге "Алгебраические трюки для программиста". Там ещё описан алгоритм без умножения, только сдвиги, сложения и битовые операции. Можно попробовать адаптировать для AVR его, тогда выигрыш во времени будет значительный.]]></description>
			<dc:creator>Nobody</dc:creator>
			<pubDate>Fri, 18 Jan 2013 05:30:40 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2412</guid>
		</item>
		<item>
			<title>Nobody says:</title>
			<link>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2411</link>
			<description><![CDATA[ Это итерационная формула Герона, если добавить ещё одну итерацию, то точность увеличится.]]></description>
			<dc:creator>Nobody</dc:creator>
			<pubDate>Fri, 18 Jan 2013 02:58:15 +0000</pubDate>
			<guid>https://chipenable.ru/index.php/programming-avr/item/144-sqrt-root.html#comment-2411</guid>
		</item>
	</channel>
</rss>
