Как написать степень в delphi

Возведение числа в действительную степень

Как, никто этого еще не придумал?

Взглянем на исходный код функции Power из модуля Math, любезно предоставленный Borland Software:

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

(1) x**y = exp(ln(x**y)) = exp(y*ln(x)).

Что плохого в таком подходе к решению? Во-первых, в набор инструкций FPU не входит ни операция вычисления exp(x), ни взятия натурального логарифма ln(x). Соответственно, результат вычисляется в несколько этапов, в то время как можно пойти более прямым путем, как будет показано ниже. За счет этого падает скорость вычисления; кроме того, здесь действует интуитивное правило, которое грубо можно сформулировать так: чем больше операций выполняется над числом с плавающей запятой в регистрах сопроцессора, тем больше будет и суммарная погрешность результата.

Давайте проведем инвентаризацию. Какие инструкции сопроцессора связаны с возведением в степень или взятием логарифма? Приведу краткую выдержку из [1] и [2]:

Вот, в общем-то, и все. Но уже на первый взгляд этого хватает, чтобы понять, что задача может быть решена более прямо, чем предлагает RTL Borland Delphi.

Действительно, почему не заменить показатель степени в (1) на 2? Ведь неперово число отнюдь не является родным для двоичной арифметики! Тогда получится

Это выражение для x**y в соответствии с вышеозначенными пятью инструкциями можно представить как композицию функций в таком виде:

Так как вычислить f(z) в одно действие невозможно, приходится считать так:

Формулы (4)-(6) естественно выражаются таким ассемблерным кодом:

Перед выполнением этого фрагмента кода нужно убедиться, что биты управления округлением в слове управления FPU установлены в режим округления к нулю. В Delphi это проще всего сделать при помощи функции SetRoundMode (модуль Math):

Так как на процессорах Intel Pentium IV последовательное многократное переключение между двумя (но не более) состояниями слова управления FPU выполняется гораздо быстрее, чем на ранних моделях, можно рассчитывать, что даже в тех ситуациях, когда придется перемежать вызов этого фрагмента кода с действиями, требующими иного режима округления, при работе на современной технике это не приведет к чрезмерным дополнительным временным затратам. Подробности см., например, в [3].

Полный код работоспособной функции на Object Pascal выглядит так:

Имеет смысл создать перегруженные версии функции для различных типов аргументов FLOATTYPE, так как на практике часто главным недостатком встроенной функции является то, что она (как и все вызываемые ею функции) принимает в качестве аргументов действительные числа типа Extended, что приводит к весьма существенным затратам на конвертирование форматов при загрузке в стек FPU.

Эксперименты показали, что предложенный вариант функции возведения в степень повышает точность вычислений на один-два знака после запятой. Так как автору было несколько лень писать медленный код для сверхточного возведения в степень с целью проверки точности предложенного алгоритма, то эксперимент заключался в сравнении результатов со значением, получающемся в стандартном калькуляторе Windows. Если верить его справочной службе, вычисления в нем производятся с точностью до 32 десятичных знаков после запятой, что позволяет полагаться на него как на источник эталонных значений.

К сожалению, выигрыш в скорости абсолютно не ощущается. Это вполне объяснимо: согласно приложению C ( “IA-32 Instruction Latency and Throughput” ) документа [3], из всего этого фрагмента основная вычислительная нагрузка ложится на трансцендентные (ответственность за не вполне корректное применение термина ложится не на меня, а на господ из Intel) операции, а именно – FYL2X, FRNDINT, F2XM1 и FSCALE. Количество же этих операций в предложенном алгоритме и их общее число в реализации функций ln(x) и exp(x) в RTL Delphi одинаково.

Конечно, хотелось бы увеличить и скорость вычислений. Но мир не идеален, и за это придется расплачиваться все той же точностью. Как правило, в каждой ситуации существует предел допустимых погрешностей при расчетах. В иллюстративных целях я задался максимальной допустимой относительной погрешностью 0,0001=0,1%. В действительности, как будет видно из графиков относительной погрешности, удалось достичь еще большей точности.

Читайте также:  Как правильно пишется слово приехать

Дальнейшие наши действия должны состоять в том, чтобы исключить трансцендентные математические операции. Ясно, что всякое представление в виде конечной композиции элементарных арифметических операций некоторой функции, неразложимой в такую композицию, является приближением исходной функции. То есть задача ставится так: нужно приблизить используемые трансцендентные функции композициями элементарных операций, оставаясь при этом в допустимых для погрешности пределах.

Аппроксимация функции 2x

Эта мера позволит нам избавиться сразу и от длительной F2XM1, и от выполняющейся ненамного быстрее FSCALE.

Вот как это сделал я.

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

Выполнение этого фрагмента изменяет содержимое регистра EAX.

Если построить график относительной погрешности, становится видно, что в пределах каждого из 1998 отрезков он имеет форму кривой с одним максимумом, сходящей к нулю на концах отрезка. При этом пределы колебаний величины погрешности остаются постоянными на всех отрезках, кроме нескольких последних – на них погрешность возрастает. Если не принимать во внимание эти отрезки, и ограничить область допустимых значений аргумента числом 990 (т.е. x x достаточно показать ее график на двух последних допустимых для значений x отрезках:


Рисунок 1. Максимальная погрешность приближения функции Exp2=2**x (при x менее 990) не превышает 0,004%.

Мы отсекли отрезки, лежащие правее точки x =990. Следовательно, размер таблицы коэффициентов можно несколько сократить: индекс последнего элемента должен быть 990*2=1980, а не 1998. “Лишние” 19 последних строк таблицы можно просто удалить. Логично также изменить текст комментария в начале функции Exp2.

Новый вариант функции возведения в степень

Изменим реализацию возведения в степень в соответствии с предложенной аппроксимацией для 2**x:

В этом фрагменте используется инструкция FCOMIP, впервые появившаяся на процессорах Pentium Pro. Любителям антиквариата придется использовать вместо пары команд FCOMIP / JE блок

Вдобавок в этом случае изменяется регистр EAX.

Результаты тестирования отражены на графиках:


Рисунок 2. Временные затраты: New_Power – новая функция, Power – из состава RTL Borland Delphi.

Подпись X-0.511 на оси абсцисс отражает тот факт, что при проведении испытаний брались значения целые значения X, к которым затем прибавлялось число 0.511, чтобы гарантировать, что основание степени – число нецелое (т.е. чтобы рассматривать по возможности общий случай).

Черная линия поверх красного набора – сглаженные временные затраты функции Power, фиолетовая поверх синего – функции New_Power.

Замеры временных затрат производились с помощью инструкции RDTSC (процессоры начиная с Pentium):

RDTSC возвращает в регистровой паре EDX:EAX число тактов процессора, прошедших с момента последнего сброса (reset). Машинный код инструкции – 0Fh, 31h.

Относительная погрешность ведет себя на удивление стабильно, изменяясь в пределах от 0 до 0,0040%. Поэтому достаточно представительным множеством значений аргумента является, к примеру, промежуток (0, 1000).


Рисунок 3.

В случае показателя степени 17 колебания становятся намного чаще, однако общая картина та же.

Аппроксимация функции log2x и “специализация” возведения в степень

Логарифмирование плохо поддается аппроксимации с помощью кубических сплайнов – точнее, мне удалось это сделать, причем с весьма высокой точностью, но лишь ценой проигрыша по времени в сравнении с использованием FYL2X. Однако здесь есть что предпринять и не прибегая к сплайнам.

Как известно, функция ln(1+x) при |x| ln(1+x)=x-x 2 /(1*2)+x 3 /(1*2*3)+…+ x i /i!+…

Это позволяет построить еще один вариант функции возведения в степень для значений основания, близких к 1. В нем нет инструкции FYL2X, а вместо нее присутствует блок инструкций, помеченных символом “ * ” (знак “

” означает приближенное равенство):

Таким образом, нам в этом случае (при x, близких к 1) удается избавиться от всех инструкций FPU, принадлежащих к группе трансцендентных, что приводит к впечатляющему росту производительности:

Читайте также:  Как правильно написать посколько или поскольку


Рисунок 4. Временные затраты: New_Power_XNear1 – специализированный вариант New_Power.

К сожалению, с ростом показателя степени максимальная погрешность растет, оставаясь, впрочем, в оговоренных пределах (т.е. меньше 0,1%; более того – меньше 0,01%) даже при очень больших показателях:


Рисунок 5.

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

Очень познавательно чтение следующих документов:

Источник

Как написать степень в delphi

Здравствуйте, aleckstein, Вы писали:

A>Не подскажите каким образом в Delphi можно возвести некоторую переменную (или число) в n-ую степень?

Здравствуйте, aleckstein, Вы писали:

A>Не подскажите каким образом в Delphi можно возвести некоторую переменную (или число) в n-ую степень?

От: defrag
Дата: 09.10.03 13:28
Оценка: +1

Здравствуйте, aleckstein, Вы писали:

A>Не подскажите каким образом в Delphi можно возвести некоторую переменную (или число) в n-ую степень?

Функции Power и IntPower в юните Math

От: akasoft
Дата: 09.10.03 17:36
Оценка:

Здравствуйте, aleckstein, Вы писали:

A>Не подскажите каким образом в Delphi можно возвести некоторую переменную (или число) в n-ую степень?

Ну и я влезу. Со старинной формулой, что тянется что-ли с D3. Весь смысл в математике, ну а реализация такова, какова была нужна мне самому.

Вывод: надо учить математику.

От: Hacker_Delphi
Дата: 09.10.03 18:21
Оценка:
От: s.ts
Дата: 10.10.03 06:24
Оценка:

Здравствуйте, akasoft, Вы писали:

A>Здравствуйте, aleckstein, Вы писали:

A>>Не подскажите каким образом в Delphi можно возвести некоторую переменную (или число) в n-ую степень?

A>Ну и я влезу. Со старинной формулой, что тянется что-ли с D3. Весь смысл в математике, ну а реализация такова, какова была нужна мне самому.

A>

A>Вывод: надо учить математику.

Это точно

От: Аноним
Дата: 10.10.03 12:01
Оценка:

Здравствуйте, aleckstein, Вы писали:

A>Не подскажите каким образом в Delphi можно возвести некоторую переменную (или число) в n-ую степень?

Power(Base, Exponent);
or
IntPower(Base, Exponent);

От: Dimonka
Дата: 10.10.03 12:47
Оценка:

Здравствуйте, DanilB, Вы писали:

DB>Здравствуйте, aleckstein, Вы писали:

DB>chis = 1;
DB>ch = 2;
DB>for(i = 0; i
DB> chis = chis * ch;

Ваша степень больше на логический сдвиг смахивает..

Poprobuyte ispolzovat’ Automation dlya svyazi s Excel, a v Excel nuzhno sodat’ vremennuyu tablizu iz N stolbzov i soschitat’ proizvedenie.
Edinstvenniy minus takogo podhoda — neobhodimost’ rasprostranyat’ vmeste s programmoy instolnik MS Office. Takim obrazom, predlozhennoe reshenie priemlemo tolko dlya bolshih kommercheskih proektov.

От: Sinclair http://corp.ingrammicro.com/Solutions/Cloud.aspx
Дата: 12.10.03 12:04
Оценка:
От: DanilB
Дата: 13.10.03 02:37
Оценка:

Здравствуйте, Dimonka, Вы писали:

D>Здравствуйте, DanilB, Вы писали:

DB>>Здравствуйте, aleckstein, Вы писали:

DB>>chis = 1;
DB>>ch = 2;
DB>>for(i = 0; i
DB>> chis = chis * ch;

D>Ваша степень больше на логический сдвиг смахивает..

От: Аноним
Дата: 13.10.03 05:17
Оценка:

Так точно, господин Злыгостев. А где бы найти нормальный online-перекодировщик, не подскажете? А то вот что выходит:

Попробуыте исползовать Аутоматион для связи с Ехцел, а в Ехцел нужно содать временнуыу таблизу из Н столбзов и сосчитать произведение.
Единственниы минус такого подхода — необходимость распространять вместе с программоы инстолник МС Оффице. Таким образом, предложенное решение приемлемо толко для болших коммерческих проектов.

От: Sinclair http://corp.ingrammicro.com/Solutions/Cloud.aspx
Дата: 13.10.03 08:10
Оценка:

Попробуйте исползовать Аутоматион для связи с Ехцел, а в Ехцел нужно содать временную таблизу из Н столбзов и сосчитать произведение.
Единственний минус такого подхода — необходимость распространять вместе с программой инстолник МС Оффице. Таким образом, предложенное решение приемлемо толко для болших коммерческих проектов.

От: Slicer [Wirkwood] https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 13.10.03 09:58
Оценка:

Thanx.
будет день — будет пища, а пока inet из мест общегo пользoвания.

Источник

Создайте кнопку для возведения X в целочисленную степенью написать прогу на delphi с формой

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Создайте кнопку для возведения X в целочисленную степеньY
Помогите пожалуйста решить задачу, знаю что это очень простая задача, но я только начал изучать.

Читайте также:  Самира на английском как написать

Функция возведения целого числа а в целочисленную степень b
/*Функция возведения целого числа а в целочисленную степень b*/ #include int.

В целочисленном массиве найти и напечатать те элементы, которые являются степенью 2. Написать функцию, проверяющую, является ли число степенью 2.
В целочисленном массиве найти и напечатать те элементы, которые являются степенью 2. Написать.

как написать прогу быстрого сканирования портом компа на delphi
как написать прогу быстрого сканирования портом компа на delphi:help::help:

Записывайтесь на профессиональные IT-курсы здесь

Решение

DenNik, давно, так что запамятовал.

Решение

Обучайтесь IT-профессиям с гарантией трудоустройства здесь.

Написать функцию для возведения в степень
Написать функцию для поднесения в степень и написать решение примера. Pascal.

Создайте кнопку для нахождения значений функции Z=Arcsin(2X+5Y).
Здраствуйте создал на Делфи калькулятор в него нужно добавить кнопку для нахождения данной функций.

Создайте кнопку для нахождения значений функции Z=Cos(4X-2Y)
Здравствуйте, создала на Делфи калькулятор, в него нужно добавить кнопку для нахождения данной.

Изменить программу для возведения в куб вместо возведения в квадрат
нужно изменить программу в турбо ассемблере так чтобы она не в квадрат возводила а в куб!! str1 DB.

Создайте кнопки для выбора двух цветов и кнопку Старт
Создайте кнопки для выбора двух цветов и кнопку Старт. После нажатия кнопки Старт надпись должна.

Написать рекурсивную функцию для возведения числа в степень
Написать рекурсивную функцию для возведения числа в степень.

Или воспользуйтесь поиском по форуму:

Изучайте английский язык в крупнейшей европейской школе Skyeng

Источник

Как написать степень в delphi

Подскажите, как можно реализовать возведение числа в произвольную степень, например 2.2, 5.69 и т.д., плиз!


Anatoly Podgoretsky ( 2003-11-29 21:43 ) [1]

По английски это Power


Александр из Минска ( 2003-11-29 21:58 ) [2]

Да, да. Power в модуле Math


Mr.Nobody ( 2003-11-29 22:32 ) [3]

А еще можно выпендриться и реализовать самому.

a=b^k => ln(a)=ln(b^k) => ln(a)=k*ln(b) => exp(ln(a))=exp(k*ln(a)) => a=exp(k*ln(a))

т.е. в Delphi exp(k*ln(a)) даст Вам a в степени k


Александр из Минска ( 2003-12-01 16:08 ) [4]

>Александр из Минска © (01.12.03 16:08) [4]
А каким образом ВЫ это реализуете «вручную», без Дельфи (или это ГЛЮК Дельфи)?
Если знаете, выложите решение для отрицательного «b» и дробного (НЕ ЧЁТНОГО) «k».
Спасибо


Думкин ( 2003-12-01 17:40 ) [6]


> [5] Floppy (01.12.03 16:19)

А в чем проблема? Одно условие и все, а поделить всегда можно.


Александр из Минска ( 2003-12-01 17:48 ) [7]


nikkie ( 2003-12-01 18:09 ) [8]

>Александр из Минска
чушь не порите

function Power(const Base, Exponent: Extended): Extended;

Description
Power raises Base to any power. For fractional exponents or exponents greater than MaxInt, Base must be greater than 0.


Александр из Минска ( 2003-12-02 20:17 ) [9]


> Александр из Минска © (02.12.03 20:17) [9]

For fractional exponents or exponents greater than MaxInt, Base must be greater than 0.
Математику давно проходили? И, похоже, все больше мимо?


Александр из Минска ( 2003-12-02 22:44 ) [11]

to Nikolay M.
Можете по-русски написать? Все же работает. Что Вам не нравится?
А математику я до сих пор изучаю (10-ый класс)!


Александр из Минска ( 2003-12-02 23:00 ) [12]

Все понятно. Но к сожалению, я этого не знаю!


Nikolay M. ( 2003-12-03 09:14 ) [13]


Думкин ( 2003-12-03 10:42 ) [14]

> [13] Nikolay M. © (03.12.03 09:14)

Можно, только надо в комплексные числа окунаться.


> Думкин © (03.12.03 10:42) [14]

Угу. А есть еще гиперкомплексные. А можно вообще не зацикливаться на вещественных числах, а работать с произвольными группами или полями. А еще я и не такие слова знаю :?)
Тока не уверен, что Math.Power меня поймет :?)


Amoeba ( 2003-12-03 12:55 ) [16]

Источник

Простые слова
Adblock
detector