Glidande Medelvärde C Code Avr


Jag har provat några löpande medelvärden för att utjämna ändringen i ADC-data i AtMega48 för att styra ljus (PWM) när man roterar en kruka (ADC). Filtren (pseudokoder): Jag observerade att filtren är mycket trevliga. Men långsamt som svar som förväntas. Jag letar efter en teknik som Exponentiell glidande medelvärde. Sade att vara mer lyhörd. Är det något annat som det här? Som det står: var ligger mellan 0 och 1. Hur kodas och optimeras de kodvisa (utan att använda floats) Eller Hur konverterar jag flottorna till motsvarande heltal för att göra kod små, snabba och lyhörda. och jag behöll en annan så att det inte fungerar som förväntat. Eftersom Idve ändrar alla variablerna för att flyta. Vänligen koncentrera dig inte om följande uttalande för tillfället utan anteckning. Att hålla floats i min kodbas fyller programminnet från 45 till 137, om du kan implementera med minimal overhead genom att begränsa binära fraktioner. Jag har använt detta med bra resultat. Ta det befintliga resultatet, Skift det N placerar rätt att dela med 2N Dra det från det befintliga resultatet. Lägg till nya data Det här är inte så snabbt att ändra med en stegändring i inmatningsdata som du kan önska, men är lätt att implementera och effektivt som ett filter i många fall. Du kan påskynda sitt svar genom att göra informella beslut om sitt beteende i fall som är för olika. t ex upprätthålla ett antal sekventiella ingångar som är mer än någon gräns som är annorlunda än det befintliga resultatet. Om denna räkning överstiger ett tröskelvärde ändrar du N-delningsförhållandet med en viss faktor. T. ex. N är vanligtvis 4- resultat flyttas rätt 4 gånger 16 klyftan. Om ingången är mer än xxx bort från svaret gör det bara två skiftningar höger och multiplicera det nya provet med 4 innan du lägger till. Svarat 4 oktober 12 kl 6: 08som andra har nämnt, bör du överväga ett filter för IIR (oändligt impulssvar) istället för det FIR-filter (ändliga impulssvar) du använder nu. Det finns mer till det, men vid första anblicken implementeras FIR-filter som uttryckliga omvälvningar och IIR-filter med ekvationer. Det speciella IIR-filtret som jag använder mycket i mikrokontroller är ett enkeltpoligt lågpassfilter. Detta är den digitala motsvarigheten till ett enkelt R-C-analogfilter. För de flesta applikationer kommer dessa att ha bättre egenskaper än det boxfilter som du använder. De flesta användningarna av ett lådfilter som jag stött på är ett resultat av att någon inte uppmärksammar sig i digital signalbehandlingsklass, inte som ett resultat av att de behöver sina speciella egenskaper. Om du bara vill dämpa högfrekvenser som du vet är buller, är ett enkelspalt lågpassfilter bättre. Det bästa sättet att implementera en digitalt i en mikrokontroller är vanligtvis: FILT lt-- FILT FF (NEW - FILT) FILT är en del av kvarhållande tillstånd. Detta är den enda beständiga variabeln du behöver för att beräkna detta filter. NEW är det nya värdet som filtret uppdateras med denna iteration. FF är filterfraktionen. vilket justerar filtrets tyngd. Titta på denna algoritm och se till att för FF 0 är filtret oändligt tungt eftersom utmatningen aldrig ändras. För FF 1, är det verkligen inget filter alls eftersom utmatningen bara följer ingången. Användbara värden är däremellan. På små system väljer du FF att vara 12 N så att multiplikationen med FF kan utföras som en rätt skift med N bitar. FF kan till exempel vara 116 och multiplicera med FF därför en högerväxling av 4 bitar. Annars behöver det här filtret endast en subtrahera och en tillägg, även om siffrorna vanligtvis behöver vara bredare än ingångsvärdet (mer om numerisk precision i ett separat avsnitt nedan). Jag brukar ta AD-avläsningar betydligt snabbare än de behövs och tillämpa två av dessa filter kaskad. Detta är den digitala ekvivalenten av två R-C-filter i serie och dämpas med 12 dBoctave ovanför rullningsfrekvensen. Men för AD-avläsningar är det vanligtvis mer relevant att titta på filtret i tidsdomänen genom att överväga sitt stegsvar. Detta berättar hur snabbt ditt system kommer att se en förändring när den sak du mäter ändras. För att underlätta utformningen av dessa filter (vilket bara betyder att välja FF och bestämma hur många av dem som ska kaskad) använder jag mitt program FILTBITS. Du anger antalet skiftbitar för varje FF i den kaskadade serien med filter, och det beräknar stegsvaret och andra värden. Faktum är att jag brukar köra detta via mitt wrapper script PLOTFILT. Det här körs FILTBITS, vilket gör en CSV-fil, sedan plottar CSV-filen. Till exempel här är resultatet av PLOTFILT 4 4: De två parametrarna till PLOTFILT betyder att det kommer att finnas två filter kaskad av typen som beskrivits ovan. Värdena på 4 anger antalet skiftbitar för att inse multipliceringen med FF. De två FF-värdena är därför 116 i detta fall. Det röda spåret är enhetens stegsvar, och är det viktigaste att titta på. Detta säger till exempel att om ingången ändras omedelbart, kommer utmatningen av det kombinerade filtret att lösa sig till 90 av det nya värdet i 60 iterationer. Om du bryr dig om 95 avvecklingstid måste du vänta på 73 iterationer och för 50 avvecklingstid bara 26 iterationer. Det gröna spåret visar utmatningen från en enda fullamplitudspik. Detta ger dig en uppfattning om slumpmässigt brusundertryck. Det verkar som om inget enda prov kommer att orsaka mer än en 2,5 förändring i utmatningen. Det blå spåret är att ge en subjektiv känsla av vad detta filter gör med vitt brus. Det här är inte ett noggrant test eftersom det inte finns någon garanti för vad exakt innehållet i slumpmässiga siffror valts som den vita brusinmatningen för denna körning av PLOTFILT. Dess enda för att ge dig en grov känsla av hur mycket det kommer att squashed och hur smidig det är. PLOTFILT, kanske FILTBITS, och massor av andra användbara saker, speciellt för PIC-firmwareutveckling finns i programvarulicens för PIC Development Tools på min nedladdningssida för program. Tillagt om numerisk precision jag ser från kommentarerna och nu ett nytt svar att det finns intresse att diskutera antalet bitar som behövs för att implementera detta filter. Observera att multipliceringen med FF kommer att skapa logg 2 (FF) nya bitar under binärpunkten. På små system är FF vanligen valt att vara 12 N så att denna multiplication faktiskt realiseras av en rättväxling av N bitar. FILT är därför vanligtvis ett fast punkts heltal. Observera att detta inte ändrar någon av matematiken från processorns synvinkel. Om du till exempel filtrerar 10 bitars AD-avläsningar och N 4 (FF 116) behöver du 4 fraktion bitar under 10 bitars heltal AD-värden. En av de flesta processorer, du gör 16 bitars heltalstransaktioner på grund av 10-bitars AD-avläsningar. I det här fallet kan du fortfarande göra exakt samma 16 bitars heltalsoperationer, men börja med AD-avläsningarna vänster skiftad med 4 bitar. Processorn känner inte skillnaden och behöver inte. Att göra matte på hela 16 bitars heltal fungerar om du anser att de är 12,4 fast punkt eller sann 16 bitars heltal (16,0 fast punkt). I allmänhet behöver du lägga till N bitar varje filterpole om du inte vill lägga till ljud på grund av den numeriska representationen. I exemplet ovan skulle det andra filtret av två behöva ha 1044 18 bitar för att inte förlora information. I praktiken på en 8-bitars maskin betyder det att du använder 24-bitars värden. Tekniskt sett skulle bara den andra polen av två behöva det bredare värdet, men för enkelhetsgraden för fasta program använder jag vanligtvis samma representation, och därmed samma kod, för alla poler i ett filter. Vanligtvis skriver jag en subrutin eller ett makro för att utföra en filterpoleoperation och applicera sedan den på varje pol. Om en subrutin eller ett makro beror på huruvida cykler eller programminne är viktigare för det specifika projektet. I vilket fall som helst använder jag en del repetillstånd för att skicka NEW till subrutinemacroen, som uppdaterar FILT, men laddar också in i samma skrapläge NYHET var in. Det gör det enkelt att tillämpa flera poler eftersom den uppdaterade filmen av en pol är den nya av nästa. När en subrutin är användbar för att få en pekare till FILT på vägen in, som uppdateras till strax efter FILT på väg ut. På så sätt fungerar subrutinen automatiskt på efterföljande filter i minnet om det kallas flera gånger. Med ett makro behöver du inte en pekare eftersom du skickar in adressen för att fungera vid varje iteration. Kodsexempel Här är ett exempel på ett makro som beskrivits ovan för en PIC 18: Och här är ett liknande makro för en PIC 24 eller dsPIC 30 eller 33: Båda dessa exempel implementeras som makron med min PIC assembler preprocessor. som är mer kapabel än någon av de inbyggda makroanläggningarna. Clabacchio: Ett annat problem som jag borde ha nämnt är implementering av firmware. Du kan skriva en enkelpolig lågpassfilter subrutin en gång och applicera den flera gånger. Faktum är att jag vanligtvis skriver en sådan subrutin för att ta en pekare i minnet till filtertillståndet, sedan få det förbi pekaren så att det kan kallas i följd lätt för att realisera flerpoliga filter. Ndash Olin Lathrop Apr 20 12 på 15:03 1. Tack så mycket för dina svar - alla av dem. Jag bestämde mig för att använda det här IIR-filtret, men det här filtret används inte som ett Standard LowPass-filter, eftersom jag behöver genomsnittliga räknevärden och jämför dem för att upptäcka ändringar i en viss räckvidd. eftersom dessa värdena har mycket olika dimensioner beroende på maskinvaran ville jag ta ett genomsnitt för att kunna reagera på dessa maskinvarespecifika ändringar automatiskt. ndash sensslen 21 maj 12 kl 12:06 Om du kan leva med begränsningen av en kraft av två antal objekt i genomsnitt (dvs 2,4,8,16,32 etc) så kan delningen enkelt och effektivt göras på en lågpresterande mikro med ingen dedikerad delning eftersom det kan göras som en bitskift. Varje växlingsrätt är en kraft av två t. ex.: OP-enheten trodde att han hade två problem, delade i en PIC16 och minne för hans ringbuffert. Detta svar visar att uppdelningen inte är svår. Visserligen behandlar det inte minnesproblemet, men SE-systemet tillåter partiella svar, och användare kan ta något från varje svar för sig själva, eller till och med redigera och kombinera andra svar. Eftersom några av de andra svaren kräver en delningsoperation är de likaledes ofullständiga eftersom de inte visar hur man effektivt uppnår detta på en PIC16. ndash Martin Apr 20 12 at 13:01 Det finns ett svar för ett riktigt glidande medelfilter (aka boxcar filter) med mindre minne krav, om du inte har något emot downsampling. Dess kallas ett kaskad integratorkamfilter (CIC). Tanken är att du har en integrator som du tar skillnader över över en tidsperiod, och den viktigaste minnesbesparande enheten är att genom nedsampling behöver du inte lagra alla värden på integratorn. Det kan implementeras med hjälp av följande pseudokod: Din effektiva glidande medellängd är decimationFactorstatesize, men du behöver bara behålla programpunkter med stateize. Självklart kan du få bättre prestanda om din stateize och decimationFactor är krafter på 2, så att divisionen och återstående operatörer blir ersatta av skift och mask-ands. Postscript: Jag håller med Olin om att du alltid bör överväga enkla IIR-filter före ett glidande medelfilter. Om du inte behöver en boxkarters frekvens-nuller, kommer ett 1-poligt eller 2-poligt lågpassfilter troligen att fungera bra. Å andra sidan, om du filtrerar i syfte att decimera (med en högprovsränta inmatning och medelvärdet för att användas av en lågprocess) kan ett CIC-filter vara precis vad du letar efter. (speciellt om du kan använda stateize1 och undvika ringbufferten helt och hållet med bara ett enda tidigare integratorvärde) Det finns en djup analys av matematiken bakom användningen av det första ordningens IIR-filter som Olin Lathrop redan har beskrivit över på Digital Signal Processing stack exchange (innehåller massor av vackra bilder.) Ekvationen för detta IIR-filter är: Detta kan implementeras med bara heltal och ingen delning med följande kod (kan behöva lite felsökning när jag skriver från minnet.) Detta filter approximerar ett glidande medelvärde av de sista K-proverna genom att ange värdet av alfa till 1K. Gör det här i föregående kod genom att definiera BITS till LOG2 (K), dvs för K 16 set BITS till 4, för K 4 set BITS till 2, etc. (Jag bekräftar koden som anges här så snart jag får en ändring och redigera det här svaret om det behövs.) svarat den 23 juni kl 12:04 Hittar ett enkelpoligt lågpassfilter (glidande medelvärde, med cutoff-frekvens CutoffFrequency). Mycket enkelt, väldigt snabbt, fungerar bra och nästan inget minne överhuvudtaget. Obs! Alla variabler har räckvidd bortom filterfunktionen, förutom det som passerat i newInput Note: Detta är ett enstegsfilter. Flera steg kan kaskadas tillsammans för att öka filterets skärpa. Om du använder mer än ett steg måste du justera DecayFactor (som gäller Cutoff-Frequency) för att kompensera. Och självklart allt du behöver är de två linjerna placerade någonstans, de behöver inte sin egen funktion. Detta filter har en ramp-up tid innan det glidande medelvärdet representerar det för ingångssignalen. Om du behöver förbi denna ramp-up-tid kan du bara initiera MovingAverage till det första värdet av newInput istället för 0, och hoppas att den första newInput inte är en outlier. (CutoffFrequencySampleRate) har ett intervall mellan 0 och 0,5. DecayFactor är ett värde mellan 0 och 1, vanligen nära 1. Envärdig flotta är tillräckligt bra för de flesta saker, jag föredrar bara dubblar. Om du behöver hålla fast med heltal kan du konvertera DecayFactor och Amplitude Factor till fraktionella heltal, där täljaren lagras som heltalet och nämnaren är ett heltalseffekt på 2 (så att du kan byta till höger som nämnare snarare än att dela upp under filterslingan). Om du exempelvis använder DecayFactor 0.99 och du vill använda heltal kan du ange DecayFactor 0.99 65536 64881. Och sedan när du multiplicerar med DecayFactor i din filterslinga, skiftar du bara resultatet 16. För mer information om detta, en utmärkt bok online, kapitel 19 om rekursiva filter: dspguidech19.htm PS För det Moving Average-paradigmet, kan ett annat sätt att ställa in DecayFactor och AmplitudeFactor som kan vara mer relevant för dina behov, vi kan säga att du vill ha det föregående, cirka 6 objekt i genomsnitt, gör det diskret, youd lägg till 6 objekt och dela med 6, så Du kan ställa in AmplitudeFactor till 16 och DecayFactor till (1.0 - AmplitudeFactor). Svarade 14 maj 12 kl 22:55 Alla andra har kommenterat grundligt om nyttan av IIR vs FIR, och på power-of-two division. Jag gillar bara att ge några detaljer om genomförandet. Nedan fungerar bra på små mikrokontroller utan FPU. Theres ingen multiplikation, och om du behåller N en kraft av två, är hela uppdelningen bit-shifting med en cykel. Grundläggande FIR-ringbuffert: Håll en löpbuffert med de sista N-värdena och en kör SUM av alla värden i bufferten. Varje gång ett nytt prov kommer in, subtrahera det äldsta värdet i bufferten från SUM, ersätt det med det nya provet, lägg till det nya provet till SUM och mata ut SUMN. Modifierad IIR ringbuffert: Håll igång SUM av de sista N-värdena. Varje gång ett nytt prov kommer in, SUM - SUMN, lägg till i det nya provet och mata ut SUMN. besvarad 28 aug 13 kl 13:45 Om jag läser dig rätt, beskriver du ett första-order IIR-filter, det värde som du subtraherar är det äldsta värdet som faller ut men istället är det genomsnittet av tidigare värden. Första ordningens IIR-filter kan säkert vara användbart, men jag är inte säker på vad du menar när du föreslår att utsignalen är densamma för alla periodiska signaler. Vid en provkvot på 10 kHz matar en 100 Hz kvadratvåg i ett 20-stegs filter med en signal som stiger jämnt för 20 prover, sitter högt för 30, sjunker jämnt för 20 prover och sitter lågt för 30. En första order IIR filter. ndash supercat Aug 28 13 på 15:31 kommer att ge en våg som kraftigt börjar stiga och gradvis nivåer nära (men inte vid) inmatnings maximalt, så börjar det kraftigt och faller gradvis av nära (men inte vid) inmatningsminimum. Mycket annorlunda beteende. Ndash supercat Aug 28 13 på 15:32 Ett problem är att ett enkelt glidande medel kan eller inte kan vara användbart. Med ett IIR-filter kan du få ett fint filter med relativt få beräkningar. Den FIR du beskriver kan bara ge dig en rektangel i tid - en sync i freq - och du kan inte hantera sidloberna. Det kan vara väl värt att kasta in ett fåtal heltal multipliceras för att göra det till en fin symmetrisk avstämningsbar FIR om du kan spara klockan. Scott Scott Seidman Aug 29 13 på 13:50 ScottSeidman: Inget behov av multiplicerar om man helt enkelt har varje steg i FIR-enheten, antingen matar in genomsnittet av inmatningen till det aktuella läget och dess tidigare lagrade värde och lagrar sedan inmatningen (om man har det numeriska området, man kan använda summan snarare än genomsnittet). Huruvida det är bättre än ett lådfilter beror på applikationen (stegresponsen av ett lådfilter med en total fördröjning på 1 ms, till exempel, kommer att ha en otäck d2dt-spik när ingången ändras och igen 1 m senare men kommer att ha det minsta möjligt ddt för ett filter med totalt 1 ms fördröjning). ndash supercat Aug 29 13 vid 15:25 Som mikeselektrisk material sa, om du verkligen behöver minska dina minnesbehov och du inte har något emot att ditt impulsrespons är exponentiellt (istället för en rektangulär puls) skulle jag gå för ett exponentiellt glidande medelfilter . Jag använder dem i stor utsträckning. Med den typen av filter behöver du ingen buffert. Du behöver inte lagra N tidigare prover. Bara en. Så, dina minneskrav får skära ner med en faktor N. Dessutom behöver du ingen delning för det. Endast multiplikationer. Om du har tillgång till flytande punkträkning, använd flytande punktmultiplikationer. Annars gör du multipelantal och går till höger. Vi är dock 2012, och jag rekommenderar dig att använda kompilatorer (och MCU) som låter dig arbeta med flytande punktnummer. Förutom att vara mer minneseffektivt och snabbare (du behöver inte uppdatera objekt i någon cirkulär buffert), skulle jag säga att det också är mer naturligt. eftersom ett exponentiellt impulsrespons matchar bättre hur naturen beter sig, i de flesta fall. svarat 20 april 12 kl 9:59 Ett problem med IIR-filtret som nästan berört av olin och supercat men tydligen ignoreras av andra är att avrundningen introducerar en viss oriktighet (och eventuellt biastruncation). förutsatt att N är en kraft av två, och endast heltalsräkning används, eliminerar växlingsrätten systematiskt LSB: erna i det nya provet. Det betyder att hur länge seriet någonsin kan vara, kommer genomsnittet aldrig att ta hänsyn till dem. Antag till exempel en långsamt minskande serie (8,8,8, 8,7,7,7, 7,6,6,) och antar att medelvärdet verkligen är 8 i början. Fist 7-provet kommer att ge genomsnittet till 7, oavsett filterstyrkan. Bara för ett prov. Samma historia för 6, etc. Tänk nu på motsatsen. serien går upp. Medelvärdet kommer att förbli på 7 för alltid, tills provet är stort nog för att få det att förändras. Naturligtvis kan du korrigera för bias genom att lägga till 12N2, men det går inte att lösa precisionsproblemet. i så fall kommer den minskande serien att stanna för alltid vid 8 tills provet är 8-12 (N2). För N4 till exempel behåller något prov över noll genomsnittet oförändrat. Jag tror att en lösning för det skulle innebära att en ackumulator av de förlorade LSB: erna finns. Men jag gjorde inte det tillräckligt långt för att få kod redo, och jag är inte säker på att det inte skulle skada IIR-strömmen i några andra fall av serier (till exempel om 7,9,7,9 skulle vara genomsnittliga till 8 då). Olin, din tvåstegskaskad skulle också behöva någon förklaring. Menar du att du håller två genomsnittsvärden med resultatet av den första matas in i den andra i varje iteration. Vad är nyttan av detta Om du har medelvärdet på N-prover, multiplicerar du genomsnittsvärdet med N, lägg till det nya provet och dela med N1. Det får INTE dig ett glidande medelvärde. Du måste vara villig att lagra 150 prover. Sedan, när du får ett nytt prov, multiplicera medeltalet med 150, subtrahera det äldsta, lägg till det nyaste och dela med 150. Sätt det nyaste i bufferten 150 och ta bort det äldsta. Det finns andra system som håller NAverage som minskar multiplikationerna lite. Jim Wagner Oregon Forskning Elektronik, Konsultation Div. Tangent, OR, USA orelectronics Kleinstein Nivå: Posting Freak Anställd: Sat. 22 september 2007 Inlagd av Kleinstein. Sol. 18 januari 2009 - 04:34 Det finns inget sätt att spara de sista N (ca 150) proverna om det behövs det verkliga rörliga genomsnittet för varje position. 150 Samles borde fortfarande passa in i RAM. Du kan dock spara multiplikationerna. Lägg till det nya provet och dra ut den sista som faller. Dela sedan summan av N för resultatet och behåll summan för nästa steg. Devision blir mycket lättare om du kan använda 128 prov. Nivå: 10k Postman Anställd: Lör. 12 februari 2005 Plats: Wormshill, England Inlagd av david. prentice. Sol. 18 jan 2009 - 04:51 PM genomsnittliga totalt antal prover. newaverage (totalt nytt) (prov 1) Om du är orolig för att rapportera ett giltigt medel tills antalet prov är 150, försenar du din rapport tills den är giltig. 16000 prover med regelbundna inter passar enkelt i en lång total. Du delar upp när du ombeds rapportera det genomsnittliga värdet. Alternativt beräknar du medelvärdet och återställer totalt 150 exemplar. Du rapporterar detta medel till nästa beräkning. Lite som hastigheten på min cykeldator. Framhjulet måste göra mer än en revolution innan hastigheten kan beräknas. curtvm Nivå: Raving Lunatic Anställd: Ons. 21 sep 2005 Inlagd av curtvm. Mon. 19 jan 2009 - 04:40 (detta är samma som Kleinsteins idé). Nivå: 10k Postman Anställd: Månad 19 februari 2001 Plats: Wisconsin USA Upplagt av theusch. Mon. 19 jan 2009 - 02:58 PM Med hjälp av beskrivningen, rullande medelvärde över ett stort antal prover, är signalen långsam. Om jag var tvungen att generalisera mina appar, är det typiskt att stänga loopen varje 500ms. Jag har ADC som tar kontinuerlig (avbrottsdriven) provtagning av alla använda AD-prover som lagrar den råa behandlingen i en array. Varje 10 ms en eller flera konverteringar har gjorts på varje kanal. (Vid en 57600 ADC klocka som är 226usconversion med ISR-överhead kanske 250us, så cirka 40 omvandlingar var 10ms.) Vid 10ms-punkten lägger jag till det råvärde som representerar det senaste konverteringsresultatet till totalt för varje kanal. Varje 500ms medelvärdet används för att stänga appslingan. Detta fungerar bra för långsamma signaler som termistorer, strömdragningsavläsningar och styrspänningar. Summa-genomsnittet tar ut mycket av bullret och avläsningarna är typiskt rockstabila. (Det har funnits många trådar om observerad bobble i ADC-avläsningar.) Observera att med användning av summan i stället för genomsnittet bevarar ett par mer låga bitar, men heck - även en långsam signal kan börja förändras i ett segment av Det 500m så vad är poängen Nu behöver snabbare rörliga signaler eller de som kräver snabbare svar en annan inställning. En vanlig situation för mig är att övervaka den råa DC-enheten för inkommande strömförlust. Den signalen kan väl vara rålikad AC och har mycket krusning. Eller det kan ha andra faktorer som kan göra det gyrat. I dessa fall gör jag ett enkelt medelvärde som Kleinstein, med det nya provet som har en vikt för att ändra föregående värde. Nej, inte ett riktigt rullande medelvärde eftersom alla prover inte upprätthålls. För effektövervakning kan det nya provet vara 12 eller 14 eller 18 vikt, empiriskt bestämt vad som bäst fungerar i ett visst fall. Nedan är koden från en app där 12 var för grov och den sista som användes 116: Du kan sätta läppstift på en gris, men det är fortfarande en gris. Ive har aldrig träffat en gris som jag inte tyckte om, så länge du har lite salt och peppar. Genomsnittlig Enkelt glidande medelvärdeSimple glidande medelvärde Du uppmanas att lösa den här uppgiften enligt uppgiftsbeskrivningen, med vilket språk du kanske vet. Beräknar det enkla glidande medlet av en serie siffror. Skapa en stateful funktionsklassinstans som tar en period och returnerar en rutin som tar ett tal som argument och ger ett enkelt glidande medelvärde av dess argument hittills. Ett enkelt glidande medelvärde är en metod för att beräkna ett medelvärde av en ström av siffror genom att endast beräkna de senaste 160 P 160-talen från strömmen, 160 var 160 P 160 är känd som perioden. Det kan genomföras genom att anropa en initialiseringsrutin med 160 P 160 som sitt argument 160 I (P), 160, som sedan ska returnera en rutin som, när den kallas med enskilda successiva medlemmar i en ström av tal, beräknar medelvärdet av (upp till), de senaste 160 P 160 av dem, kan ringa denna 160 SMA (). Ordet 160 stateful 160 i uppgiftsbeskrivningen hänvisar till behovet av 160 SMA () 160 för att komma ihåg viss information mellan samtal till den: 160 Perioden, 160 P 160 En beställd behållare med minst de senaste 160 P 160 numren från var och en av Dess enskilda samtal. Stateful 160 betyder också att successiva samtal till 160 I (), 160 initialiseraren, 160 ska returnera separata rutiner som gör 160 inte 160 delade sparade tillstånd så att de kunde användas på två oberoende dataströmmar. Pseudokod för implementering av 160 SMA 160 är: Denna version använder en bestående kö för att hålla de senaste p-värdena. Varje funktion som returneras från init-moving-genomsnittet har sitt tillstånd i en atom som håller ett kövärde. Denna implementering använder en cirkulär lista för att lagra siffrorna i fönstret i början av varje iterationspekare hänvisar till listcellen som håller värdet bara förflyttning ur fönstret och ersätts med det tillförda värdet. Använda en avslutningsredigering För närvarande kan denna sma vara nogc eftersom den allokerar en stängning på högen. Några flyktanalyser kunde ta bort heapfördelningen. Använda en strukturredigering Den här versionen undviker hällanslutningen av stängningen och håller data i stapelramen för huvudfunktionen. Samma utmatning: För att undvika att de flytande punkts approximationerna fortsätter att växa upp och växer, kan koden utföra en periodisk summa på hela cirkulärkön. Denna implementering producerar två (funktion) objekt delningstillstånd. Det är idiomatiskt i E att separera inmatning från utgång (läs från skriv) istället för att kombinera dem i ett objekt. Strukturen är densamma som implementeringen av Standard DeviationE. Elixirprogrammet nedan genererar en anonym funktion med en inbäddad period p, som används som perioden för det enkla glidande medlet. Körningsfunktionen läser numerisk ingång och skickar den till den nyupprettade anonyma funktionen och inspekterar sedan resultatet till STDOUT. Utgången visas nedan, med medelvärdet, följt av den grupperade ingången, som utgör grunden för varje glidande medelvärde. Erlang har stängningar, men oföränderliga variabler. En lösning är då att använda processer och ett enkelt meddelande som passerar baserat API. Matrisspråken har rutiner för att beräkna glidningsavvikelserna för en given sekvens av objekt. Det är mindre effektivt att slinga som i följande kommandon. Ständigt uppmanar till en ingång I. Som läggs till i slutet av en lista L1. L1 kan hittas genom att trycka på 2ND1, och medel kan hittas i ListOPS Tryck på ON för att avsluta programmet. Funktion som returnerar en lista som innehåller den genomsnittliga data för det medföljande argumentet Program som returnerar ett enkelt värde vid varje tillkännagivande: Listan är listan som medelvärde: p är perioden: 5 returnerar den genomsnittliga listan: Exempel 2: Använda programmet movinav2 , 5) - Initialisering av glidande medelberäkning, och definiera en period på 5 movinav2 (3, x): x - nya data i listan (värde 3) och resultatet lagras på variabel x och visas movinav2 (4, x) : x - ny data (värde 4), och det nya resultatet lagras på variabel x och visas (43) 2. Beskrivning av funktionen movinavg: variabel r - är resultatet (den genomsnittliga listan) som kommer att returneras variabel i - är indexvariabeln, och den pekar på slutet av dellistan som listan är medeltal. Variabel z - en hjälparvariabel Funktionen använder variabel i för att bestämma vilka värden av listan som ska beaktas i nästa genomsnittliga beräkning. Vid varje iteration pekar variabel I till det sista värdet i listan som kommer att användas i medelberäkningen. Så vi behöver bara ta reda på vilka som kommer att vara det första värdet i listan. Vanligtvis måste man överväga p-element, så det första elementet kommer att vara det som indexeras av (i-p1). Men vid de första iterationerna kommer denna beräkning normalt att vara negativ, så kommer följande ekvation att undvika negativa index: max (i-p1,1) eller, ordna ekvationen, max (i-p, 0) 1. Men antalet element på de första iterationerna kommer också att vara mindre, det korrekta värdet kommer att vara (slutindex - startindex 1) eller, ordna ekvationen, (i - (max (ip, 0) 1) 1) och sedan , (I-max (ip, 0)). Variabel z har det gemensamma värdet (max (ip), 0) så startindex kommer att vara (z1) och nummervärdena blir (iz) mitt (lista, z1, iz) kommer att returnera listan över värde som kommer att vara medelvärde ( .) summerar dem summa (.) (iz) ri kommer att genomsöka dem och lagra resultatet på lämpligt ställe i resultatlistan fp1 skapar en partiell applikation som fastställer (i detta fall) andra och tredje parametrar

Comments