Куда все подевались?

Страницы: 1
RSS
Куда все подевались?
 
Заметил, что на этом форуме практически перестали появляться новые сообщения. Да и тусуются буквально 5 шт. старожилов.
Почему? куда всё ушло?
Люди перестали пользоваться QUIK?
Для роботов все переехали на другую платформу? какую?
Любители-лудоманы вовсе убежали с биржи рынка? совсем или перебежали на другую? какую?
 
Когда у меня вопросы возникают, я закидываю в gpt руководсктво и начинаю его трясти вопросами, иногда получается хорошо. Может другие также делают
 
Это же форум по проблемам, вопросам, а не про жизнь на Марсе. Плюс почти все уже было обсуждено не по одному разу. Разработчики терминала заняты чем-то еще.
Также стоит учитывать, что терминал рассчитан на MOEX, где торгуют "три калеки", тем более сейчас лето.
 
Тоже интересен этот вопрос. Неужели все торгуют через мобильные приложения и веб-интерфейсы брокеров?
Знаю, что частные фонды своих прогеров имеют, которым достаточно документации. Ещё заметил, что ТП ARQA периодически предлагает сразу на почту им писать про баги, поэтому часть обсуждений могла туда уйти.
 
Ну господа, на Вас не угодить!  :smile:
Форум конечно не про Марс и не про жизнь на МОЕХ, форум про глюки, которыми радуют разработчики.
Данная веточка же про возможности организации алгоритмической торговли, не смотря ни на какие глюки, с помощью языка луа, по крайней мере так ее воспринимаю.
Позволю себе не согласиться, что все уже обсудили, у меня вопросов больше, чем ответов начиная от технологических, и заканчивая стратегиями.
Согласен gpt простые вопросы помогает решать. Но сколько копий сломано, пока разобрался с кольцевым буфером, возможно для кого то просто и понятно,
но у меня это заняло "вагон и маленькую тележку" времени. А ведь прием классный для работы с памятью. Возможно снова велосипед, но вспомнил, про двухфакторную очередь (которую выкладывал), на ее основе реализовал буфер (надо наверно выложить, может кому с экономит то самое время, которое сможет потратить на зарабатывание своих миллионов).
Лето, отпуска конечно ликвидность упала, протолкнуть объемы сложно, тут и самое время обсудить стратегии капитал менеджмента.
 
Цитата
VPM написал:
Но сколько копий сломано, пока разобрался с кольцевым буфером
Выложи пожалуйста свой вариант кольцевого буфера, мне тоже он был нужен, вот что через gpt получилось (может кому-то нужно):
Код
function CycleRowIndex(arr_input, operation)
   -- Пример вызова, есть массив arr:
   -- local currentRow = CycleRowIndex(arr, "current") выдаст текущую строку
   -- local firstRow = CycleRowIndex(arr, "first") выдаст первую строку
   -- local shiftRow = CycleRowIndex(arr, "shift") "сдвинет" строку
    if #arr_input == 0 then
        return nil -- если массив пуст, возвращаем nil
    end
    
    arr_input.currentRow = arr_input.currentRow or 0 -- используем строковый ключ
    local arraySize = #arr_input
    local currentRow

    if operation == "first" then
        local lastRow = arr_input.currentRow
        if lastRow <= arraySize then
            currentRow = 1
        else
            currentRow = ((lastRow) % arraySize) + 1
        end
    elseif operation == "current" then
        currentRow = (arr_input.currentRow) % arraySize
        if currentRow == 0 then
            if arr_input.currentRow >= arraySize then
                currentRow = arraySize
            else
                currentRow = 1
            end
        end
    elseif operation == "shift" then
        currentRow = (arr_input.currentRow) % arraySize + 1
        arr_input.currentRow = arr_input.currentRow + 1
    end
    
    return currentRow
end
 
Цитата
Айдар написал:
вот что через gpt получилось (может кому-то нужно):
Интересно какой был prompt, что такой монстр вышел?
 
Цитата
Nikolay написал:
Цитата
Айдар написал:
вот что через gpt получилось (может кому-то нужно):
Интересно какой был prompt, что такой монстр вышел?
gpt4, но это конечно же не с первого раза, долгое общение было с ним.
 
Цитата
Айдар написал:
gpt4, но это конечно же не с первого раза, долгое общение было с ним.
Вопрос был не про модель, а про запрос. Впрочем, если это не с первого раза, то лучше руками писать. Хотя, возможно, это Lua - малопопулярный язык, выборка обучения мала.
 
Классический кольцевой буфер, также известный как циклический буфер или кольцевая очередь, используется для хранения фиксированного количества последних значений в массиве.
Кольцевой буфер реализован в виде массива фиксированного размера (в данном случае из трех элементов) и индекса, который отслеживает текущее положение для записи нового значения. Когда индекс достигает конца массива, он обнуляется, что позволяет использовать массив циклически.
Инициализация: В начале работы буфер заполняется нулями, и индекс указывается на первый элемент.
Обновление:
  - При каждом вызове функции новое значение записывается в текущий индекс буфера.
  - После записи индекс обновляется. Если индекс достигает конца массива, он обнуляется (возвращается к началу массива)
Обработка данных: Для выполнения вычислений используются значения из буфера.
Именно здесь появляются не удобство применения классического кольцевого буфера!
То есть, значения записываются 1,2,3, и снова 1,2,3, ...

Пример реализации методов с использованием кольцевого буфера:
Кольцевой буфер в классе `Ehlers.ChannelPDF` используется для хранения последних трех значений, которые обновляются при каждом новом баре.
Буфер работает по принципу FIFO, где новое значение заменяет самое старое значение, и обеспечивается циклический доступ к элементам массива
Код
-- Метод FilterSmooth
local ChannelPDF={}
function ChannelPDF:FilterSmooth()
    local F = {0, 0, 0}  -- кольцевой буфер на 3 элемента
    local index = 1
    local start = true
    return function(I, x)
        if I == 1 or start then
            F = {0, 0, 0} -- Инициализация значений
            index = 1 -- Инициализация индекса
            start = false
        end
        F[index] = x -- Обновление (новое значение)
        local y = F[index] + 2 * F[(index - 1 - 1) % 3 + 1] + F[(index - 2 - 1) % 3 + 1]
        y = y and (y >= 1 and 0.999 or y <= -1 and -0.999 or x) or y
        index = index % 3 + 1 -- Обновление индекса
        return y
    end
end
Циклическая запись данных и последовательная индексация свечей, приводит к сложностям (по крайней мере для меня) при получении данных из буфера и их последующей обработкой в формулах.
Для небольших задач пойдет. Но есть подход лучше - использовать двусвязную очередь для реализации кольцевого буфера!
Расписал подробно для общего понимания вопроса.  
 
Цитата
VPM написал:
-- Метод FilterSmooth
local ChannelPDF={}
function ChannelPDF:FilterSmooth()
   local F = {0, 0, 0}  -- кольцевой буфер на 3 элемента
   local index = 1
   local start = true
   return function(I, x)
       if I == 1 or start then
           F = {0, 0, 0} -- Инициализация значений
           index = 1 -- Инициализация индекса
           start = false
       end
       F[index] = x -- Обновление (новое значение)
       local y = F[index] + 2 * F[(index - 1 - 1) % 3 + 1] + F[(index - 2 - 1) % 3 + 1]
       y = y and (y >= 1 and 0.999 or y <= -1 and -0.999 or x) or y
       index = index % 3 + 1 -- Обновление индекса
       return y
   end
end
хорошо бы еще пример с доказательством,
что это лучше чем , что?
 
nikolz,  Ну Вы в своем амплуа, целую повесть я тут написал
Цитата
VPM написал:
Расписал подробно для общего понимания вопроса
Это моя реализация (частный случай но показательный) как можно использовать
Цитата
VPM написал:
Классический кольцевой буфер, также известный как циклический буфер или кольцевая очередь, используется для хранения фиксированного количества последних значений в массиве.
Айдар,  попросил мой вариант
Цитата
Айдар написал:
Выложи пожалуйста свой вариант кольцевого буфера, мне тоже он был нужен, вот что через gpt получилось (может кому-то нужно):
Я привел пример, с указанием на недостатки - для кольцевого буфера, извлечение данных зависит от конкретного сценария использования и потребностей, и указал на лучший подход
Цитата
VPM написал:
Но есть подход лучше - использовать двусвязную очередь для реализации кольцевого буфера!
двусвязную очередь мы ранее обсуждали этому вопросу посвящалась целая ветка. Могу сказать как использую, у меня это модуль - класс, подгрузил в начале алгоритма
local Queue = require("QueueClass") и делаешь необходимое количество экземпляров определенной длины, определённой направленности, такие как FIFO, LIFO, или извлечение по произвольному условию. В моем примере local ChannelPDF={} это три экземпляра разной длины массивы. И это удобно! А что нужно доказывать я не понимаю. Здесь на мой взгляд просто нужно пользуетесь, не нужно не пользуетесь. Повторюсь вот модуль
Код
-- класс двусвязной очереди:

local Queue = {}
Queue.__index = Queue
function Queue.new()
    return setmetatable({first = 0, last = -1}, Queue)
end
function Queue:push_left(value)
    local first = self.first - 1
    self.first = first
    self[first] = value
end
function Queue:pop_left()
    local first = self.first
    if first > self.last then error("queue is empty") end
    local value = self[first]
    self[first] = nil  -- to allow garbage collection
    self.first = first + 1
    return value
end
function Queue:push_right(value)
    local last = self.last + 1
    self.last = last
    self[last] = value
end
function Queue:pop_right()
    local last = self.last
    if self.first > last then error("queue is empty") end
    local value = self[last]
    self[last] = nil  -- to allow garbage collection
    self.last = last - 1
    return value
end
return Queue
 
Судите сами вот тот же пример. Изменение класса Ehlers.ChannelPDF, чтобы использовать двусвязную очередь для кольцевого буфера.
Код
local Queue = require("QueueClass")  -- класс Queue сохранен в файле QueueClass.lua

Ehlers.ChannelPDF = {}
Ehlers.ChannelPDF.__index = Ehlers.ChannelPDF
function Ehlers.ChannelPDF.new(FSettings, ds)
    local self = setmetatable({}, Ehlers.ChannelPDF)
    
    self.FSettings = FSettings or {}
    self.ds = ds
    self.P = FSettings.period or 4
    self.up = FSettings.up or 1.0
    self.dw = FSettings.dw or -1.0
    
    self.I1 = 0
    self.hh, self.ll = 0, 0
    
    self.Lead = Queue.new()
    
    self:initialize()
    
    return self
end
function Ehlers.ChannelPDF:initialize()
    self.fTransformFisher = self:TransformFisher()
    self.fTransformIFisher = self:TransformIFisher()
    
    self.fFilterSmooth = self:FilterSmooth()
    self.fFilterLead = self:FilterLead()
    
    self.I1 = 0
    self.Lead = Queue.new()
end

function Ehlers.ChannelPDF:FilterSmooth()
    local F = Queue.new()
    return function(I, x)
        if I == 1 then
            F = Queue.new()
            for _ = 1, 3 do F:push_right(0) end
        end
        F:pop_left()
        F:push_right(x)
        local y = 2 * F[1] + F[2] - F[3]
        y = y and (y >= 1 and 0.999 or y <= -1 and -0.999 or x) or y
        return y
    end
end

Называть наверно следует, кольцевая очередь, используется для хранения фиксированного количества последних значений в массиве
 
Прежде чем кидать примеры, необходимо понимать зачем и как это будет использоваться.
Для примера, простая задача оптимизации памяти, не требует никаких сложных конструкций. Например, так сделано в примера расчета индикаторов от ARQA.
Задача хранить в массиве не более 5 элементов. Решение - просто рассчитывать индекс массива через операцию %. Все.

Для примера, массив на 5 элементов. Значит индекс 12 будет записан в элемент 12%5 = 2

А методы сдвига, нужны если необходимы очереди, стеки. Которые прекрасно реализуются и без кольца.
 
Цитата
VPM написал:
Судите сами вот тот же пример. Изменение класса Ehlers.ChannelPDF, чтобы использовать двусвязную очередь для кольцевого буфера.
Код
  
Называть наверно следует, кольцевая очередь, используется для хранения фиксированного количества последних значений в массиве
Вы правы, я не читаю форумы полностью.
Когда зашел, то и прочитал.
Спасибо, что написали примеры.
-------------------
Возможно не понял Ваши объяснения.
попробую задать вопросы снова, если не сложно расскажите свое понимание.
--------------------
Возьмем для начала беседы ваш кольцевой буфер на три элемента.
Код
- Метод FilterSmooth
local ChannelPDF={}
function ChannelPDF:FilterSmooth()
    local F = {0, 0, 0}  -- кольцевой буфер на 3 элемента
    local index = 1
    local start = true
    return function(I, x)
        if I == 1 or start then
            F = {0, 0, 0} -- Инициализация значений
            index = 1 -- Инициализация индекса
            start = false
        end
        F[index] = x -- Обновление (новое значение)
        local y = F[index] + 2 * F[(index - 1 - 1) % 3 + 1] + F[(index - 2 - 1) % 3 + 1]
        y = y and (y >= 1 and 0.999 or y <= -1 and -0.999 or x) or y
        index = index % 3 + 1 -- Обновление индекса
        return y
    end
end
Мне непонятно, в чем его выгода и что же он делает.
------------------
Полагаю, что есть другие вариант решения.
=============  
Если мы с Вами говорим об одном и том же,
то кольцевой буфер на три элемента позволяет нам получить лишь три последних элемента последовательности чисел.
---------------------------
Т е это буфер данных, но его глубина всего три элемента. Верно?
--------------------------
Т е это его недостаток, а за это Вы полагаете, получается экономия памяти . Верно?
===============
Если я правильно Вас понял, то вот элементарное альтернативное решение:
Код
local F={0,0,0} 
local function shiftArray(x) local x=F[1] F[1]=F[2] F[2]=F[3] F[3]=x  return x end

Массив F имеет размер как у Вас.
В нем хранится последние 3 элемента. При записи нового , первый выталкивается.
Что не так?
И в чем преимущество Вашего решения?  
 
Цитата
Nikolay написал:
Прежде чем кидать примеры, необходимо понимать зачем и как это будет использоваться.
Так именно это я и отношу в не достаток такого подхода
Цитата
VPM написал:
Я привел пример, с указанием на недостатки - для кольцевого буфера, извлечение данных зависит от конкретного сценария использования и потребностей, и указал на лучший подход
По сложности не намного сложней описанного Вами подхода, класс удобен, в моем примере (посчитал) аж 5 экземпляров очередей, различного размера, размер легко меняется, как и направление то есть динамичен структуру можно менять в процессе эксплуатации , универсальность (действует принцип по образу и подобию создаются экземпляры)
Динамичность позволяет менять структуру в процессе эксплуатации, например при поиске оптимальных параметров. Универсальность один раз разобрался и забыл.
Да и потом я не настаиваю что это единственный подход, я говорю что это удобно.
 
Цитата
nikolz написал:
Мне непонятно, в чем его выгода и что же он делает. ------------------Полагаю, что есть другие вариант решения.
Цитата
VPM написал:
Классический кольцевой буфер, также известный как циклический буфер или кольцевая очередь, используется для хранения фиксированного количества последних значений в массиве.
Наверняка есть, Айдар,  выложил свой, я могу в виде класса выложить.
Цитата
nikolz написал:
Если я правильно Вас понял, то вот элементарное альтернативное решение:Кодlocal F={0,0,0}
local function shiftArray(x) local x=F[1] F[1]=F[2] F[2]=F[3] F[3]=x  return x end

Массив F имеет размер как у Вас. В нем хранится последние 3 элемента. При записи нового , первый выталкивается. Что не так? И в чем преимущество Вашего решения?  
Если Вы загрузите в SciTe это пример он не будет работать. Вот я уже попробовал
Код
local F={0,0,0} 
local function shiftArray(x) local x=F[1] F[1]=F[2] F[2]=F[3] F[3]=x  return x end
for I=1,10 do
print(shiftArray(I), F[1], F[2], F[3] )
end
ответы:
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
0   0   0   0
>Exit code: 0    Time: 0.4064
 
Так и нет ответа, зачем сдвиги, если самое быстрое решение это перезапись элемента и расчет очередного корректного индекса.
 
nikolz,  Вот так работает
Код
local F = {0, 0, 0}
local function shiftArray(x)
    -- Сдвигаем элементы массива
    F[3] = F[2]
    F[2] = F[1]
    F[1] = x -- Записываем новый элемент в конец массива
    return F -- Возвращаем массив целиком (или можете возвращать только F[1], если нужно)
end

for I=1,10 do
print(shiftArray(I), F[1], F[2], F[3] )
end

table: 0000000002710d50   1   0   0
table: 0000000002710d50   2   1   0
table: 0000000002710d50   3   2   1
table: 0000000002710d50   4   3   2
table: 0000000002710d50   5   4   3
table: 0000000002710d50   6   5   4
table: 0000000002710d50   7   6   5
table: 0000000002710d50   8   7   6
table: 0000000002710d50   9   8   7
table: 0000000002710d50   10   9   8
>Exit code: 0    Time: 0.3958

2. Альтернативное решение с использованием кольцевого буфера

local F = {0, 0, 0}
local index = 0
local function addElement(x)
    index = (index % 3) + 1
    F[index] = x
   return F
end
for I=1,10 do
print(addElement(I), F[1], F[2], F[3] )
end

table: 00000000025a1150   1   0   0
table: 00000000025a1150   1   2   0
table: 00000000025a1150   1   2   3
table: 00000000025a1150   4   2   3
table: 00000000025a1150   4   5   3
table: 00000000025a1150   4   5   6
table: 00000000025a1150   7   5   6
table: 00000000025a1150   7   8   6
table: 00000000025a1150   7   8   9
table: 00000000025a1150   10   8   9
 
Цитата
Nikolay написал:
Так и нет ответа, зачем сдвиги, если самое быстрое решение это перезапись элемента и расчет очередного корректного индекса.
А я не уверен что есть сдвиги, алгоритм помнит индексы, обновляет эти индексы.
Сам пример FilterSmooth(), подразумевает что можно менять длину и веса простыми способами.

Ну хорошо если знаете алгоритм, приведите пример алгоритма "самое быстрое решение это перезапись элемента и расчет очередного корректного индекса" динамически меняющего индекс, длину и веса?  
 
Цитата
VPM написал:
Ну хорошо если знаете алгоритм, приведите пример алгоритма "самое быстрое решение это перезапись элемента и расчет очередного корректного индекса" динамически меняющего индекс, длину и веса?  
Что это значит "динамически меняющего индекс, длину и веса"? Если речь про очередь, стек, то одна задача. Если речь про хранение в массиве определенного числа элементов, скажем 100 и не более, то это другая.
 
Nikolay,  Ну смотрите на моем примере выше при использовании двусвязной очереди, все Вами описанные задачи по сути сводятся к одному задать длину и метод извлечения, то есть ввести входные данные, которые можно менять динамически ведя дополнительные расчеты, или жестко установить. А вот что у меня получилось из примера nikolz, я в кольцевом буфере попытался поменять порядок хранения данных. Ну в общем то и не получается поменять.
Код
 
Цитата
VPM написал:
Цитата
nikolz написал:
Мне непонятно, в чем его выгода и что же он делает. ------------------Полагаю, что есть другие вариант решения.
 
Цитата
VPM написал:
Классический кольцевой буфер, также известный как циклический буфер или кольцевая очередь, используется для хранения фиксированного количества последних значений в массиве.
Наверняка есть, Айдар,  выложил свой, я могу в виде класса выложить.
Цитата
nikolz написал:
Если я правильно Вас понял, то вот элементарное альтернативное решение:Кодlocal F={0,0,0}
local function shiftArray(x) local x=F[1] F[1]=F[2] F[2]=F[3] F[3]=x  return x end

Массив F имеет размер как у Вас. В нем хранится последние 3 элемента. При записи нового , первый выталкивается. Что не так? И в чем преимущество Вашего решения?  
Если Вы загрузите в SciTe это пример он не будет работать. Вот я уже попробовал
Код
   local  F = { 0 , 0 , 0 } 
 local   function   shiftArray (x)  local  x = F[ 1 ] F[ 1 ] = F[ 2 ] F[ 2 ] = F[ 3 ] F[ 3 ] = x   return  x  end 
 for  I =  1 , 10   do 
 print (shiftArray(I), F[ 1 ], F[ 2 ], F[ 3 ] )
 end 
ответы:
 0     0     0     0 
 0     0     0     0 
 0     0     0     0 
 0     0     0     0 
 0     0     0     0 
 0     0     0     0 
 0     0     0     0 
 0     0     0     0 
 0     0     0     0 
 0     0     0     0 
 > Exit code:  0     Time:  0.4064 
  
Пардон, опечатка.
----------------
должно быть так:
Код
 local   function   shiftArray (x)  local  z = F[ 1 ] F[ 1 ] = F[ 2 ] F[ 2 ] = F[ 3 ] F[ 3 ] = x   return  z  end 
---------------------------
 for  I =  1 , 10   do  print (shiftArray(I), F[ 1 ], F[ 2 ], F[ 3 ] )
 end 
-----------------------  
результат:
0   0   0   1
0   0   1   2
0   1   2   3
1   2   3   4
2   3   4   5
3   4   5   6
4   5   6   7
5   6   7   8
6   7   8   9
7   8   9   10
>Exit code: 0












 
Вот в этом варианте вроде работает, ну как то все сложно и сиюминутно
Код
local F = {0, 0, 0}
local index = 0
local function addElement(x)
    -- Обновляем текущий индекс с учетом кольцевого буфера
    index = (index % 3) + 1
    -- Вставляем новый элемент в текущий индекс
    F[index] = x
    
    -- Для наглядности выводим текущий массив
    local result = {}
    for i = 1, 3 do
        result[i] = F[(index - i + 3) % 3 + 1]
    end
    return result
end
 
Цитата
VPM написал:
Nikolay,  Ну смотрите на моем примере выше при использовании двусвязной очереди, все Вами описанные задачи по сути сводятся к одному задать длину и метод извлечения, то есть ввести входные данные, которые можно менять динамически ведя дополнительные расчеты, или жестко установить. А вот что у меня получилось из примера nikolz, я в кольцевом буфере попытался поменять порядок хранения данных. Ну в общем то и не получается поменять.
Код
    
Давайте вернемся к Вашей функции циклического массива на 3 элемента.
Я исправил ошибку в своем варианте и он работает.
-----------------
Предлагаю не перескакивать с одной задачи на другую, Давайте сначала закончим с Вашим вариантом циклического массива на 3
потом перейдем к связанным или нет спискам.
-------------------
Повторю свой вопрос.
Чем Ваш вариант лучше по сравнению с указанным мною примером ( могу потом написать еще проще) но давайте закончим с этим.
Что не так у меня и что лучше у Вас?
прошу подробно объяснить именно про это.
 
nikolz,  Когда Вы голову подымите чуть выше, заметите что я поправил Ваш вариант, и для сравнения выложил альтернативное решение с использованием кольцевого буфера, даже попробовал разный порядок хранения данных.  Что лучше, почему лучше, когда какой применять, решает пользователь под свои задачи. А я лишь привожу пример про универсальный способ, и показываю его преимущества, относительно других. Но в любом случае их нужно погонять в условиях когда пропадают свечи, когда вызывается по нескольку раз на одном индексе алгоритмы и прочие радости жизни алгоритмов в квике.  
 
Цитата
VPM написал:
nikolz,  Когда Вы голову подымите чуть выше, заметите что я поправил Ваш вариант, и для сравнения выложил альтернативное решение с использованием кольцевого буфера, даже попробовал разный порядок хранения данных.  Что лучше, почему лучше, когда какой применять, решает пользователь под свои задачи. А я лишь привожу пример про универсальный способ, и показываю его преимущества, относительно других. Но в любом случае их нужно погонять в условиях когда пропадают свечи, когда вызывается по нескольку раз на одном индексе алгоритмы и прочие радости жизни алгоритмов в квике.  
можете ответить кратко на мой вопрос.
Чем ваш конкретный вариант на 3 элемента лучше чем тот который я привел. Я просто написал вам то, что элементарно делается.
Так делают  сортировку 3 элементов.  
-----------------------
И так ответьте на вопросы:
Обсуждаем вот эти две функции:

Код
local ChannelPDF={}
function ChannelPDF:FilterSmooth()
    local F = {0, 0, 0}  -- кольцевой буфер на 3 элемента
    local index = 1
    local start = true
    return function(I, x)
        if I == 1 or start then
            F = {0, 0, 0} -- Инициализация значений
            index = 1 -- Инициализация индекса
            start = false
        end
        F[index] = x -- Обновление (новое значение)
        local y = F[index] + 2 * F[(index - 1 - 1) % 3 + 1] + F[(index - 2 - 1) % 3 + 1]
        y = y and (y >= 1 and 0.999 or y <= -1 and -0.999 or x) or y
        index = index % 3 + 1 -- Обновление индекса
        return y
    end
end


Код
function   shiftArray (x)  local  z = F[ 1 ] F[ 1 ] = F[ 2 ] F[ 2 ] = F[ 3 ] F[ 3 ] = x   return  z  end
Чем функция 1 лучше, чем функция 2.
Прошу Вас не отвлекаться и не рассказывать мне, где и что Вы раньше написали.
Напишите кратко и конкретно здесь
---------------
Мой ответ на мой вопрос такой:
Функция 1 сложнее, чем функция 2.
------------------
Ваш ответ?
 
nikolz,  Извините за банальность, но так сравнивают только "Х" с пальцем. Если Вы хотите провести сравнительные тесты, то нужно определим критерии по которым будут сравнивать. А сравнивать нужно хотя бы эти варианты.
Код
1. Pешение с использованием кольцевого буфера

local F = {0, 0, 0}
local index = 0
local function addElement(x)
    index = (index % 3) + 1
    F[index] = x
   return F
end
for I=1,10 do
print(addElement(I), F[1], F[2], F[3] )
end

2. Вариант. Альтернативное решение
local F = {0, 0, 0}
local function shiftArray(x)
    -- Сдвигаем элементы массива
    F[3] = F[2]
    F[2] = F[1]
    F[1] = x -- Записываем новый элемент в конец массива
    return F -- Возвращаем массив целиком (или можете возвращать только F[1], если нужно)
end

for I=1,10 do
print(shiftArray(I), F[1], F[2], F[3] )
end
А может подскажите, где я сказал, что какой то вариант лучше?
 
Может быть, потому все и разбежались, что в любом топике море оффтопа :)
 
funduk, Не уверен что по этому, а что же тогда будет являться обсуждением? Но в одном Вы правы.
И прежде чем продолжить, должен принести свои извинения, за излишнею грубость и хамство. nikolz,  извините.

Касаемо предмета обсуждения, фактически представлена реализация 3 вариантов кольцевого буфера с разными методами исполнения,
не смотря на то что изменения не значительны, но они сильно влияют на производительность алгоритма. Не вооруженным глазом видно что вариант1 быстрее варианта2.
Здесь рассуждение простые, вариант1 это всегда вставка(1 элемент), в то время как вариант2 это вставка(n элемент буфера).
Видимо фактор производительности, явился решающим для включения разработчиками данного подхода в свои индикаторы, но для меня оно интуитивно смущало из-за не прозрачного расчета индексов. Решил проверить вариант с двухсвязной очередью, дописал вариант для проверки на производительность.
И каково было мое удивление, ну в общем судите сами, вот варианты.
Код
local size = 100000 -- 3
 
do ---- 1.
--local F = {0, 0, 0}
local F = {}
for i = 1, size do
    F[i] = 0
end

local start_time = os.clock()
local function shiftArray(x)
    -- Сдвигаем элементы массива
    F[3] = F[2]
    F[2] = F[1]
    F[1] = x -- Записываем новый элемент в конец массива
    return F -- Возвращаем массив целиком (или можете возвращать только F[3], если нужно)
end
for I=1,size do
--print( shiftArray(I), F[1], F[2], F[3] )
shiftArray(I)
end
local end_time = os.clock()
print("1. Время выполнения для варианта 1:", end_time - start_time, "секунд")
end
do --local F = {0, 0, 0}
local F = {}
for i = 1, size do
    F[i] = 0
end

local start_time = os.clock()
local index = 0
local function addElement(x)
    index = (index % 3) + 1
    F[index] = x
   return F
end
for I=1,size do
--print(addElement(I), F[1], F[2], F[3] )
addElement(I)
end
local end_time = os.clock()
print("2. Время выполнения для варианта 1a:", end_time - start_time, "секунд")
end
do ---- 2.
--local F = {0, 0, 0}
local F = {}
for i = 1, size do
    F[i] = 0
end

local start_time = os.clock()
local index = 0
local function addElement(x)
    -- Обновляем текущий индекс с учетом кольцевого буфера
    index = (index % 3) + 1
    -- Вставляем новый элемент в текущий индекс
    F[index] = x
    
    -- Для наглядности выводим текущий массив
    local result = {}
    for i = 1, 3 do
        result[i] = F[(index - i + 3) % 3 + 1]
    end
    return result
end
for I=1,size do
--print('*',addElement(I), F[1], F[2], F[3] )
addElement(I)
end
local end_time = os.clock()
print("3. Время выполнения для варианта 2:", end_time - start_time, "секунд")
end
do ---- 3. Простой вариант с переменной currentIndex
local F = {}
for i = 1, 1000 do
    F[i] = 0
end

local start_time = os.clock()
local currentIndex = 1
local function addElement(x)
    F[currentIndex] = x
    currentIndex = currentIndex + 1
    if currentIndex > 1000 then
        currentIndex = 1
    end
    return F
end

for i = 1, 100000 do -- Повторяем операцию добавления 100000 раз
    addElement(i)
end

local end_time = os.clock()
print("4. Время выполнения для варианта 3:", end_time - start_time, "секунд")
end
А вот ответы:
1. Время выполнения для варианта 1:   0.009   секунд
2. Время выполнения для варианта 1a:   0.006   секунд
3. Время выполнения для варианта 2:   1.185   секунд
4. Время выполнения для варианта 3:   0.0050000000000001   секунд
>Exit code: 0    Time: 1.768
 
Примеры не равнозначны, т.к. в первой реализации функции addElement есть вывод элементов, т.е. цикл.


В общем случае алгоритм с единичным действием вставки элемента имеет константную сложность O(1), а тот, где есть сдвиги - О(n). Так что даже вопроса нет что быстрее.А скорость расчета индекса - это не то, что сильно повлияет на производительность в случае О(1).
 
Если интересует производительность, то вот результат запуска скрипта, который выше, в lua 5.4 и luajit
-------------
lua5.4
Код
1. Время выполнения для варианта 1:   0.005   секунд
2. Время выполнения для варианта 1a:   0.005   секунд
3. Время выполнения для варианта 2:   0.077   секунд
4. Время выполнения для варианта 3:   0.004   секунд
>Exit code: 0

luajit
Код
1. Время выполнения для варианта 1:   0.001   секунд
2. Время выполнения для варианта 1a:   0.001   секунд
3. Время выполнения для варианта 2:   0.015   секунд
4. Время выполнения для варианта 3:   0   секунд
>Exit code: 0
 
а это время вычисления для 1 млн.элементов для циклического массива в 1000 элементов
для стека указано время push pop
для очереди указано время записи и извлечения
Lua 5.4
Код
Время выполнения стек 0(сек):   0.048,0.051
Время выполнения очередь(сек):   0.036,0.051
>Exit code: 0

Luajit
Код
Время выполнения стек 0(сек):   0.003,0.001
Время выполнения очередь(сек):   0,0.001
 
VPM,
вот этот вариант можно  сделать еще быстрее:
это ваш вариант
Код
---- 3. Простой вариант с переменной currentIndex
local F = {} for i = 1, 1000 do  F[i]=0 end
size=1000000
local N=1024
local currentIndex = 1
local function addElement(x) F[currentIndex]=x currentIndex=currentIndex+1 if currentIndex>N then currentIndex=1 end return F end
local start_time = os.clock()
for i = 1, size do   addElement(i) end -- повторяем 1 млн.
local end_time = os.clock()
print("4. Время выполнения для варианта 3:", end_time - start_time, "секунд")
это мой вариант:
Код
local N=1024
local F = {} for i = 1,N do  F[i]=0 end
size=1000000
local currentIndex = 1
local function addElementNK(x) F[currentIndex&(N-1)]=x currentIndex=currentIndex + 1 return F end
local start_time = os.clock()
for i = 1, size do    addElementNK(i) end -- повторяем 1 млн.
local end_time = os.clock()
print("5. Время выполнения для варианта NK:", end_time - start_time, "секунд")

это результат:
Код
4. Время выполнения для варианта 3:   0.046   секунд
5. Время выполнения для варианта NK:   0.043   секунд

Пару слов без протокола.
В этих функциях лишним является оператор return F
т к нет смысла возвращать то, что изначально определено вне функции
тоже самое относится и к переменной currentIndex
нет смысла ее индексировать внутри функции, можно снаружи
в моем случае все можно записать  так:
Код
local N=1024
local F = {} for i = 1,N do  F[i]=0 end
size=1000000
local currentIndex = 1
local start_time = os.clock()
for i = 1, size do    F[currentIndex&(N-1)]=i;currentIndex=currentIndex + 1 end -- повторяем 1 млн.
local end_time = os.clock()
print("6. Время выполнения для варианта NK без функции:", end_time - start_time, "секунд")
результат:
Код
6. Время выполнения для варианта NK без функции:   0.014   секунд
 
подчистил пример тестов ранее:
Код
local size = 1000000 local N=1023  local F = {}

local function shiftArray(x)
    F[3] = F[2]    F[2] = F[1]  F[1] = x  end
start = os.clock() for I=1,size do shiftArray(I) end time = 1000000*(os.clock()- start)/size
print("1. вариант 1(мкс):",time)

local index=0;
local function addElement(x) index=(index % 3)+1 F[index] = x end
start = os.clock()  for I=1,size do addElement(I) end time = 1000000*(os.clock()- start)/size
print("2. вариант 1a(мкс):", time)

index=0;
local function addElement(x)
    index=(index%3)+1 F[index]=x
    local result = {}  for i = 1,3 do  result[i]=F[(index-i+3)%3 + 1]    end
    return result
end
local index=0 start= os.clock() for I=1,size do  addElement(I)  end time = 1000000*(os.clock()- start)/size
print("3. вариант 2:(мкс):", time)

---- 3. Простой вариант с переменной currentIndex
local cIndex = 1
local function addElement(x) F[cIndex]=x cIndex=cIndex+1 if cIndex>N then cIndex=1 end end
start = os.clock()  for i= 1, size do   addElement(i) end  time = 1000000*(os.clock()- start)/size
print("4. вариант 3(мкс):", time)

local cIndex=1
local function addElementNK(x) F[cIndex&N]=x cIndex=cIndex + 1 end
start=os.clock() for i = 1, size do    addElementNK(i) end  time = 1000000*(os.clock()- start)/size
print("5. вариант NK(мкс):", time)

local cIndex = 1
start=os.clock() for i = 1, size do F[cIndex&N]=i;cIndex=cIndex+1 end time = 1000000*(os.clock()- start)/size
print("6. вариант NK без функции(мкс):", time)

результат Lua 5.4
Код
1. вариант 1(мкс):   0.047
2. вариант 1a(мкс):   0.048
3. вариант 2:(мкс):   0.721
4. вариант 3(мкс):   0.045
5. вариант NK(мкс):   0.04
6. вариант NK без функции(мкс):   0.012
>Exit code: 0
Страницы: 1
Читают тему
Наверх