Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2007.07.29;
Скачать: [xml.tar.bz2];

Вниз

Скорость вычисления функции оставляет желать..   Найти похожие ветки 

 
pirate ©   (2007-05-18 07:53) [0]

В общем говоря, народ, такая вот проблема:
Мне потребовалась функция, почти как синус, но сигнал треугольный.
Вот что получилось:
function tri(angle:real):real;
begin
while angle>=2*pi do angle:=angle-2*pi;\\
while angle<0 do angle:=angle+2*pi;\\Ограничиваем угол в [0..2pi]
if angle<pi/2 then
result:=2*angle/pi
else if angle<1.5*pi then
result:=-2*(angle-pi/2)/pi+1
else if angle<2*pi then
result:=2*(angle-1.5*pi)/pi-1;
end;


И теперь я столкнулся с замедлением, связанным с вычислением этой функции.

Какие есть предложения по улучшению алгоритма?


 
MBo ©   (2007-05-18 09:01) [1]

Да уж - циклы зачем-то...

function SmartTri(Angle: Double): Double;
var
 d: Double;
begin
 Angle := Angle + Pi/2;
 d := 2 * Frac(Abs(Angle) / (Pi)) - 1;
 if Odd(Trunc(Angle / Pi)) then
   d := -d;
 Result := d;
end;


 
MBo ©   (2007-05-18 09:02) [2]

так проще:
 Angle := (Angle + Pi/2) / Pi;
 d := 2 * Frac(Abs(Angle)) - 1;
 if Odd(Trunc(Angle)) then
   d := -d;


 
pirate ©   (2007-05-18 09:19) [3]

Меня всегда интересовала функция Frac() - ты не мог бы доступно пояснить ее?


 
MBo ©   (2007-05-18 09:29) [4]

Так в справке же описано


 
DVM ©   (2007-05-18 10:31) [5]

Я не знаю, заменяет ли оптимизатор pi/2 на заранее вычисленное значение, но можно еще заранее вычислить pi/2, и поместить в константу.


 
DVM ©   (2007-05-18 10:40) [6]

Функция tri на маленьких значениях углов быстрее SmartTri в 2 раза
На больших значениях медленнее в сотни раз.


 
Jeer ©   (2007-05-18 11:47) [7]

Так чуть быстрее, вроде:)
7-8 kTicks, а от Mbo 8-9 kTicks

function Triangle(Value: double): double;
var B: double;
   d: integer;
const Pi2 = Pi / 2;
     Pi2I = 1 / Pi2;
begin
 d := 1;
 B := Value + Pi2;

 if (B > Pi) then begin
   B := B - Pi;
   d := -1;
 end;

 if (B > Pi) then begin
   B := B - Pi;
   d := 1;
 end;

 Result := d * (Pi2I * B - 1);
end;


 
Jeer ©   (2007-05-18 12:25) [8]

Еще вариант, при условии угла 0..1, что не ограничивает, конечно
Скорость примерно та же.

function Triangle3(omega: double): double;
begin
 if omega <= 0.25 then Result := 4 * omega
 else
   if omega >= 0.75 then
     Result := 4 * (omega - 1)
   else
     Result := 4 * (0.5 - omega);
end;


 
pirate ©   (2007-05-21 11:14) [9]

function Triangle(Value: double): double; - Не пашет. Точнее пашет, но не правильно. Что в прочем одно и т о же... :)
SmartTri меня вполне удовлетворил. Большое спасибо.
Но из одного ответа появляется новый вопрос:
В справке я не понял, как работает frac, видимо я по математическй части просто не знаю чего-то. Следовательно я не понял, как работает SmartTri. И вот теперь такое дело: Надобно аналогичную функцию, но сигнал квадратный, т.е. 1 если alpha [0..pi] и -1 если alpha [pi..2pi].
Ну, вот собственно и все.


 
Сергей М. ©   (2007-05-21 11:18) [10]


> как работает frac


Функция возвращает значение дробной части аргумента.


 
Jeer ©   (2007-05-21 11:23) [11]


> т.е. 1 если alpha [0..pi] и -1 если alpha [pi..2pi].


Ты даже с этим справиться не можешь ?


> function Triangle(Value: double): double; - Не пашет. Точнее
> пашет, но не правильно.


У меня "пашет" и правильно.


 
Сергей М. ©   (2007-05-21 11:25) [12]

Result := Max(Sign(Sin(Angle), 0);


 
pirate ©   (2007-05-21 11:41) [13]

Sorry, сам доехал, когда уже отправил.
Решение действительно предельно простое.
Только вот зачем Max? Разве Sign(Sin) не есть искомый результат?

По поводу Triangle: У меня она все время растет, и выдает очень большие значения, такие, что мне на осциллографе(часть программы) приходится ставить усиление(коэффициент обыкновенный) около 0.0001 чтобы наблюдать функцию. Вполне вероятно, что я где-то накосячил, но вроде бы я просто скопировал-вставил. Только у меня функция имеет тип real, вот и все различие.

Спасибо за оперативность! Я просто удивлен..


 
Сергей М. ©   (2007-05-21 12:00) [14]


> зачем Max? Разве Sign(Sin) не есть искомый результат?


Max нужен для приведения результата работы Sign к двум значениям - 0 и 1 (Sign возвращает -1, 0, 1, что не соответствует условию задачи)

Привести же результат вызова Max к множеству (-1, 1) проще простого.

Можно поступить еще проще:

Result := Sign(Sin(Angle));
if Result = 0 then Result := -1;


 
Jeer ©   (2007-05-21 14:33) [15]


> pirate ©   (21.05.07 11:41) [13]


У тебя в вопросе диапазон ограничен 0..2*PI
Вот и ограничивай его для Triangle.


 
Jeer ©   (2007-05-21 14:56) [16]


> Сергей М. ©   (21.05.07 12:00) [14]
>
>


Тогда уж еще проще, в случае 0..2*PI

if angle < PI then Result := 1
else Result := -1;


 
Сергей М. ©   (2007-05-21 15:06) [17]


> Jeer ©   (21.05.07 14:56) [16]


Я не стал упрощать, потому что [0..2*PI]-ограничение области определения аргумента, imho, блажь. И Автор уже получил граблями (на тестировании твоего примера) из-за этой блажи)


 
Jeer ©   (2007-05-21 15:56) [18]


> Сергей М. ©   (21.05.07 15:06) [17]


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

Вычисление угла
A := A + dA
if A > 2PI then A := A - 2PI;


 
Сергей М. ©   (2007-05-21 16:02) [19]


> логичнее ограничивать угол при его вычислении, чем встраивать
> такие возможности в функции-генераторы


Ну может и так.
Спор тут беспредметен.


> Автор делает что-то вроде программного осциллографа


Тогда логичней было бы оперировать аргументом-временем, а не углом.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2007.07.29;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.054 c
4-1171270394
Чапаев
2007-02-12 11:53
2007.07.29
Как потоку получить оповещение о выходе из suspend?


15-1183450467
Начинающий программист
2007-07-03 12:14
2007.07.29
Книга по Delphi


3-1177250760
Антон Шестаков
2007-04-22 18:06
2007.07.29
Удаление из таблиц


15-1182939839
TruePunk
2007-06-27 14:23
2007.07.29
TLSDScreen


15-1183105429
sinus
2007-06-29 12:23
2007.07.29
Delphi >> C++





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский