====== std.stats — Statistik über Zahlenfelder ====== → [[lyx_-_programmiersprache:units|Zurück zur Unit-Übersicht]] Auswertung von ''int64''-Feldern: Summe, Minimum, Maximum, Mittelwert, Median, Varianz, Standardabweichung, Suchen und Zählen. Dazu ein paar Rechenhilfen und Aggregatfunktionen für ''Map''-Werte. Alle Feldfunktionen arbeiten auf einem rohen Speicherblock mit 8 Byte Schrittweite; ''n'' zählt Elemente, nicht Bytes. **Autor:** Andreas Röne\\ **Copyright:** 2024–2025 Andreas Röne\\ **Quelle:** ''std/stats.lyx'' > **Zwei früher hier verzeichnete Defekte sind behoben.** Nachgemessen mit 1.0.21A: > > * Die ''Map*''-Aggregate rechnen wieder — für ''{1: 10, 2: 20, 3: 30}'' liefern ''MapCount''/''MapSum''/''MapMax'' die Werte 3, 60 und 30 ([[https://github.com/SEOLizer/LyX-Compiler/issues/1491|#1491]]). > * ''std.stats'' und ''std.math'' lassen sich **gemeinsam importieren**; die frühere Mehrdeutigkeit bei ''Clamp64'' und ''InRange64'' besteht nicht mehr ([[https://github.com/SEOLizer/LyX-Compiler/issues/1492|#1492]]). ===== Import ===== import std.stats; Nicht zusammen mit ''std.math'' importierbar (#1492). Zieht ''std.sort'' mit — ''ArrayMedian'' und ''ArraySort'' bauen darauf auf. ---- ===== Funktionen ===== ==== Kennzahlen ==== ^ Signatur ^ Beschreibung ^ | ''ArraySum(arr, n: int64): int64'' | Summe aller Werte | | ''ArrayCount(arr, n: int64): int64'' | Gibt ''n'' zurück — der Vollständigkeit halber | | ''ArrayMin(arr, n: int64): int64'' | Kleinster Wert; leeres Feld ergibt 0 | | ''ArrayMax(arr, n: int64): int64'' | Größter Wert; leeres Feld ergibt 0 | | ''ArrayAvg(arr, n: int64): int64'' | Mittelwert, ganzzahlig abgerundet | | ''ArrayRange(arr, n: int64): int64'' | Spannweite: Maximum minus Minimum | | ''ArrayProduct(arr, n: int64): int64'' | Produkt aller Werte; leeres Feld ergibt 0 | | ''ArraySumSquares(arr, n: int64): int64'' | Summe der Quadrate | | ''ArrayVariance(arr, n: int64): int64'' | Varianz, durch ''n'' geteilt — **Rückgabe ist ''int64''** | | ''ArrayStdDev(arr, n: int64): int64'' | Standardabweichung, ganzzahlig **abgerundet** | **Varianz und Standardabweichung sind hier ganzzahlig — das ist selten die gewünschte Antwort.** Eine Varianz ist fast nie eine ganze Zahl; ''ArrayStdDev'' rundet ab und liefert für die Werte 2…6 den Wert ''1'' statt 1,58. Bei kleinen Streuungen wird daraus ''0''. Für Statistik in ''f64'' gibt es [[lyx_-_programmiersprache:units:prob|std.prob]] — mit dem Unterschied zwischen Grundgesamtheit (''ProbVarianceP'') und Stichprobe (''ProbVarianceS''), den diese Unit gar nicht führt. ''std.stats'' bleibt richtig, wenn tatsächlich über ganze Zahlen gezählt und aggregiert wird. | ''ArrayMedian(arr, n: int64): int64'' | Mittlerer Wert — **sortiert das übergebene Feld** | Ein **leeres Feld** (''n == 0'') liefert bei allen Funktionen 0, ohne zu lesen. Beim Produkt ist das eine bewusste Abweichung von der Mathematik, wo das leere Produkt 1 wäre. Die Varianz teilt durch ''n'', nicht durch ''n − 1'' — sie beschreibt also die vorliegenden Werte selbst und ist keine Schätzung für eine größere Grundgesamtheit. ==== Suchen und Zählen ==== ^ Signatur ^ Beschreibung ^ | ''ArrayFirst(arr, n, fallback: int64): int64'' | Erster Wert, sonst ''fallback'' | | ''ArrayLast(arr, n, fallback: int64): int64'' | Letzter Wert, sonst ''fallback'' | | ''ArrayIndexOf(arr, n, value: int64): int64'' | Erste Fundstelle, ''-1'' wenn nicht enthalten | | ''ArrayLastIndexOf(arr, n, value: int64): int64'' | Letzte Fundstelle | | ''ArrayContains(arr, n, value: int64): bool'' | Ob der Wert vorkommt | | ''ArrayCountValue(arr, n, value: int64): int64'' | Wie oft der Wert vorkommt | ==== Sortieren ==== ^ Signatur ^ Beschreibung ^ | ''ArraySort(arr, n: int64): void'' | Sortiert aufsteigend — reicht an ''SortInt64'' aus [[lyx_-_programmiersprache:units:sort|std.sort]] weiter | ==== Rechenhilfen ==== ^ Signatur ^ Beschreibung ^ | ''Clamp64(value, minVal, maxVal: int64): int64'' | Wert auf einen Bereich begrenzen | | ''InRange64(value, minVal, maxVal: int64): bool'' | Ob der Wert im Bereich liegt, Grenzen eingeschlossen | | ''Percentage64(value, total: int64): int64'' | Prozentanteil, ganzzahlig; ''total == 0'' ergibt 0 | | ''AbsDiff64(a, b: int64): int64'' | Betrag der Differenz | ''Clamp64'' und ''InRange64'' gibt es namensgleich auch in ''std.math'' (#1492). ==== Map-Aggregate ==== ^ Signatur ^ Beschreibung ^ Status ^ | ''MapCount(m: int64): int64'' | Zahl der Einträge | **liefert 0** (#1491) | | ''MapSum(m: int64): int64'' | Summe der Werte | **liefert 0** (#1491) | | ''MapMin(m: int64): int64'' · ''MapMax'' · ''MapAvg'' | Kleinster/größter/mittlerer Wert | **liefert 0** (#1491) | Übergeben wird die Map als ''m as int64''. ---- ===== Beispiel ===== import std.stats; import std.alloc; fn main(): int64 { // Messreihe var a: int64 := alloc(6 * 8); poke64(a, 4); poke64(a+8, 8); poke64(a+16, 15); poke64(a+24, 16); poke64(a+32, 23); poke64(a+40, 42); PrintLn("Werte: 4 8 15 16 23 42"); PrintLn("Summe = ", IntToStr(ArraySum(a, 6))); PrintLn("Minimum = ", IntToStr(ArrayMin(a, 6))); PrintLn("Maximum = ", IntToStr(ArrayMax(a, 6))); PrintLn("Mittelwert = ", IntToStr(ArrayAvg(a, 6))); PrintLn("Spannweite = ", IntToStr(ArrayRange(a, 6))); PrintLn("Varianz = ", IntToStr(ArrayVariance(a, 6))); PrintLn("Standardabw. = ", IntToStr(ArrayStdDev(a, 6))); PrintLn("-- Suchen:"); PrintLn("IndexOf(15) = ", IntToStr(ArrayIndexOf(a, 6, 15))); PrintLn("Contains(99) = ", IntToStr(ArrayContains(a, 6, 99) as int64)); PrintLn("CountValue(8) = ", IntToStr(ArrayCountValue(a, 6, 8))); PrintLn("-- Median sortiert die Eingabe:"); var b: int64 := alloc(5 * 8); poke64(b, 50); poke64(b+8, 10); poke64(b+16, 40); poke64(b+24, 20); poke64(b+32, 30); Print("vorher: "); var i: int64 := 0; while (i < 5) { Print(IntToStr(peek64(b + i*8)), " "); i := i + 1; } PrintLn(""); PrintLn("Median = ", IntToStr(ArrayMedian(b, 5))); Print("nachher: "); i := 0; while (i < 5) { Print(IntToStr(peek64(b + i*8)), " "); i := i + 1; } PrintLn(""); return 0; } Ausgabe: Werte: 4 8 15 16 23 42 Summe = 108 Minimum = 4 Maximum = 42 Mittelwert = 18 Spannweite = 38 Varianz = 151 Standardabw. = 12 -- Suchen: IndexOf(15) = 2 Contains(99) = 0 CountValue(8) = 1 -- Median sortiert die Eingabe: vorher: 50 10 40 20 30 Median = 30 nachher: 10 20 30 40 50 ---- ===== Fallstricke ===== ==== ArrayMedian verändert das Feld ==== Um den mittleren Wert zu finden, sortiert die Funktion die Eingabe — dauerhaft, wie die Ausgabe oben zeigt. Wer die ursprüngliche Reihenfolge braucht, arbeitet auf einer Kopie: var kopie: int64 := alloc(n * 8); var i: int64 := 0; while (i < n) { poke64(kopie + i*8, peek64(arr + i*8)); i := i + 1; } var med: int64 := ArrayMedian(kopie, n); free(kopie, n * 8); Dasselbe gilt für ''ArraySort'', dort ist es allerdings der erklärte Zweck. ==== Median bei gerader Anzahl ==== Bei einer geraden Zahl von Werten gibt die Funktion das **obere** der beiden mittleren Elemente zurück, nicht deren Mittelwert: Median(10, 20, 30, 40) = 30 statistisch üblich wären 25 Wer den üblichen Wert braucht, bildet ihn selbst aus den Positionen ''n/2 − 1'' und ''n/2'' des sortierten Feldes. ==== Ganzzahlige Ergebnisse ==== Mittelwert, Varianz, Standardabweichung und Prozentangaben werden abgerundet: aus 12,3 wird 12, aus 12,5 % werden 12 %. Bei kleinen Werten fällt das ins Gewicht — ein Mittelwert von 0 kann sowohl „alle Werte sind 0" als auch „alle Werte liegen unter 1" bedeuten. Wo es genauer sein muss, vorher mit 100 oder 1000 skalieren und am Ende zurückrechnen. ==== Überlauf bei Produkt und Quadratsummen ==== ''ArrayProduct'' multipliziert ungeprüft — sechs dreistellige Werte genügen bereits für einen Überlauf. Auch ''ArraySumSquares'' und die Varianz quadrieren, ohne den Bereich zu prüfen. Bei großen Messwerten vorher überschlagen oder die Werte herunterskalieren. ---- ===== Verwandte Units ===== * [[lyx_-_programmiersprache:units:sort|std.sort]] — ''SortInt64'', Grundlage von ''ArraySort'' und ''ArrayMedian'' * [[lyx_-_programmiersprache:units:math|std.math]] — ''IntSqrt'', ''Min64''/''Max64''; **nicht zusammen importierbar** (#1492) * [[lyx_-_programmiersprache:units:list|std.list]] — dynamische Zahlenlisten mit eigener Sortierung