====== 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