Заметил, что на этом форуме практически перестали появляться новые сообщения. Да и тусуются буквально 5 шт. старожилов. Почему? куда всё ушло? Люди перестали пользоваться QUIK? Для роботов все переехали на другую платформу? какую? Любители-лудоманы вовсе убежали с биржи рынка? совсем или перебежали на другую? какую?
Это же форум по проблемам, вопросам, а не про жизнь на Марсе. Плюс почти все уже было обсуждено не по одному разу. Разработчики терминала заняты чем-то еще. Также стоит учитывать, что терминал рассчитан на MOEX, где торгуют "три калеки", тем более сейчас лето.
Тоже интересен этот вопрос. Неужели все торгуют через мобильные приложения и веб-интерфейсы брокеров? Знаю, что частные фонды своих прогеров имеют, которым достаточно документации. Ещё заметил, что ТП ARQA периодически предлагает сразу на почту им писать про баги, поэтому часть обсуждений могла туда уйти.
Ну господа, на Вас не угодить! Форум конечно не про Марс и не про жизнь на МОЕХ, форум про глюки, которыми радуют разработчики. Данная веточка же про возможности организации алгоритмической торговли, не смотря ни на какие глюки, с помощью языка луа, по крайней мере так ее воспринимаю. Позволю себе не согласиться, что все уже обсудили, у меня вопросов больше, чем ответов начиная от технологических, и заканчивая стратегиями. Согласен 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
Айдар написал: 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
Nikolay написал: Так и нет ответа, зачем сдвиги, если самое быстрое решение это перезапись элемента и расчет очередного корректного индекса.
А я не уверен что есть сдвиги, алгоритм помнит индексы, обновляет эти индексы. Сам пример FilterSmooth(), подразумевает что можно менять длину и веса простыми способами.
Ну хорошо если знаете алгоритм, приведите пример алгоритма "самое быстрое решение это перезапись элемента и расчет очередного корректного индекса" динамически меняющего индекс, длину и веса?
VPM написал: Ну хорошо если знаете алгоритм, приведите пример алгоритма "самое быстрое решение это перезапись элемента и расчет очередного корректного индекса" динамически меняющего индекс, длину и веса?
Что это значит "динамически меняющего индекс, длину и веса"? Если речь про очередь, стек, то одна задача. Если речь про хранение в массиве определенного числа элементов, скажем 100 и не более, то это другая.
Nikolay, Ну смотрите на моем примере выше при использовании двусвязной очереди, все Вами описанные задачи по сути сводятся к одному задать длину и метод извлечения, то есть ввести входные данные, которые можно менять динамически ведя дополнительные расчеты, или жестко установить. А вот что у меня получилось из примера nikolz, я в кольцевом буфере попытался поменять порядок хранения данных. Ну в общем то и не получается поменять.
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