Проблема заключается в том, что приложение на имитаторе / устройстве iOS устарело и несовместимо с текущей версией Expo, которую вы используете.
Удалите приложение Expo из симулятора iOS, и оно должно работать, или установите последнее обновление, если вы находитесь на устройстве. / 1595 Один из способов сделать это с открытым имитатором - это Erase All Content and Settings
. Затем снова запустите npm start и приложение Expo снова будет установлено на симуляторе этого устройства.
Если Вы не заботитесь слишком много о производительности, вот очень простое решение:
#light
let MovingAverage n s =
Seq.windowed n s
|> Seq.map Array.average
let avgs = MovingAverage 5000 (Seq.map float [|1..999999|])
for avg in avgs do
printfn "%f" avg
System.Console.ReadKey() |> ignore
Это повторно вычисляет среднее число каждого 'окна' с нуля, таким образом, это плохо, если окна являются большими.
В любом случае, выезд Seq.windowed:
поскольку удобно иметь в Вашем заднем кармане для таких вещей.
Вот (исправленный, я надеюсь), версия F# решения Haskell, предложенного здесь.
Править: Теперь рекурсивный хвостом, не немного быстрее, но не взрывается с n = 50000. (см. историю редактирования для non-tail-recursive версии),
let LimitedAverage n ls =
let rec loop acc i n ls =
match i with
| 0 -> acc //i counts down from n to 0, when we hit 0 we stop
| _ -> match ls with
| [] -> acc //if we hit empty list before end of n, we stop too
| x::xs -> (loop (acc + (x / float n)) (i - 1) n xs) //divide this value by n, perform average on 'rest' of list
loop 0. n n ls
LimitedAverage 50000 (List.map float [1..9999999])
//>val it : float = 25000.5
let rec MovingAverage3 n ls =
let rec acc loop i n ls =
match i with
| 0 -> List.rev acc //i counts down from n to 0, when we hit 0 we stop
| _ -> match ls with
| [] -> List.rev acc //if we hit empty list before end of n, we stop too
| x::xs -> loop (LimitedAverage2 n ls :: acc) (i - 1) n xs // limited average on whole list, then moving average on tail
loop [] (n + 1) n ls
MovingAverage3 50000 (List.map float [1..9999999])
//>val it : float list = [25000.5; 25001.5; 25002.5; ...]
Насколько я вижу, Ваш код полон let
операторы. Я не знаком с F#, но действительно делал некоторого Haskell. Функциональные средства парадигмы, не думая, о "как", но о "какой": Вы думаете первым прибыл, первым обслужен, но необходимо на самом деле просто указать семантику скользящего среднего значения.
-- the limited average of a list
limitedaverage 0 _ = 0
limited verage n (x:xs) = (x/n) + ( limited average (n-1) xs )
-- a list, transformed into a sequence of moving averages of
movingaverages n [] = []
movingaverages n (x:xs) = ( movingaverage n (x:xs) : movingaverages n xs )
Если Вы действительно заботитесь о производительности, то можно вычислить скользящее среднее значение эффективно с помощью чего-то вроде этого (предположение, что мы вычисляем скользящее среднее значение по 3-дневному окну),
Numbers[n] Running Total[n] --------- --------------- n[0] = 7 7 = Numbers[0] n[1] = 1 8 = RunningTotal[1-1] + Numbers[1] n[2] = 2 10 = RunningTotal[2-1] + Numbers[2] n[3] = 8 11 = RunningTotal[3-1] + Numbers[3] - Numbers[3-3] n[4] = 4 14 = RunningTotal[4-1] + Numbers[4] - Numbers[4-3] n[5] = 1 13 = RunningTotal[5-1] + Numbers[5] - Numbers[5-3] n[6] = 9 14 = RunningTotal[6-1] + Numbers[6] - Numbers[6-3] ... N RunningTotal[N] = RunningTotal[N-1] + Numbers[N] - Numbers[N-3]
Твердая часть об этом держится Ваше предыдущее рабочее общее количество и NumberN-окно. Я придумал следующий код:
let movingAverage days l =
seq {
let queue = new Queue<_>(days : int)
let divisor = decimal days
let total = ref 0m
for cur in l do
queue.Enqueue(cur)
total := !total + cur
if queue.Count < days then
yield (cur, 0m)
else
yield (cur, !total / divisor)
total := !total - (queue.Dequeue())
}
Эта версия не так симпатична как код Haskell, но это должно избежать проблем производительности, связанных с перевычислениями Вашего "окна" на каждом выполнении. Это сохраняет рабочее общее количество и содержит ранее используемые числа в очереди, таким образом, это должно быть очень быстро.
Только для забавы, я записал простой сравнительный тест:
#light
open System
open System.Collections.Generic
open System.Diagnostics;
let windowAverage days (l : #seq<decimal>) = Seq.windowed days l |> Seq.map (Seq.average)
let princessAverage days l =
seq {
let queue = new Queue<_>(days : int)
let divisor = decimal days
let total = ref 0m
for cur in l do
queue.Enqueue(cur)
total := !total + cur
if queue.Count < days then
yield (cur, 0m)
else
yield (cur, !total / divisor)
total := !total - (queue.Dequeue())
}
let testData =
let rnd = new System.Random()
seq { for a in 1 .. 1000000 -> decimal (rnd.Next(1000)) }
let benchmark msg f iterations =
let rec loop = function
| 0 -> ()
| n -> f 3 testData |> ignore; loop (n - 1)
let stopWatch = Stopwatch.StartNew()
loop iterations
stopWatch.Stop()
printfn "%s: %f" msg stopWatch.Elapsed.TotalMilliseconds
let _ =
let iterations = 10000000
benchmark "princessAverage" princessAverage iterations
benchmark "windowAverage" windowAverage iterations
printfn "Done"
Результаты:
princessAverage: 1670.791800 windowAverage: 2986.146900
Моя версия является ~1.79x быстрее.