Haftungsausschluss: Der Mittelwert wird von mir gebildet
Definiere das arithmetische Mittel von Zahlen als
Definiere das geometrische Mittel von Zahlen als
Definieren Sie das harmonische Mittel von Zahlen als
Definiere den quadratischen Mittelwert von Zahlen als
Der Mittelwert ( ) ist wie folgt definiert: Definiere vier Folgen ( ) alsnM1( x1, . . . , xn) = x1+ x2+ . . . + xnn
nM0( x1, . . . , xn) = x1X2. . . Xn--------√n
nM- 1( x1, . . . , xn) = n1X2+ 1X2+ . . . + 1Xn
nM2( x1, . . . , xn) = x21+ x22+ . . . + x2nn--------------√
MMeink, bk, ck, dkein0= M1( x1, . . . , xn) ,b0= M0( x1, . . . , xn) ,c0= M- 1( x1, . . . , xn) ,d0= M2( x1, . . . , xn) ,eink + 1= M1( ak, bk, ck, dk) ,bk + 1= M0( ak, bk, ck, dk) ,ck + 1= M- 1( ak, bk, ck, dk) ,dk + 1= M2( ak, bk, ck, dk)
M M ( x 1 , x 2 , . . . , x n )
Alle vier Sequenzen konvergieren zu die gleiche Zahl, .MM( x1, x2, . . . , xn)
Beispiel
Der Mittelwert von 1 und 2 wird wie folgt berechnet: Beginnen Sie mit
Dann ist
Die weitere Berechnung der Sequenzen sollte klar sein. Es ist ersichtlich, dass sie zu derselben Zahl, ungefähr , .ein0= ( 1 + 2 ) / 2 = 1,5 , b0=1∗2−−−−√=2–√≈1.4142,c0=211+12=43≈1.3333,d0=12+222−−−−−−−√=52−−√≈1.5811.
ein1=1.5+1.4142+1.3333+1.58114≈1.4571,b1=1.5∗1.4142∗1.3333∗1.5811−−−−−−−−−−−−−−−−−−−−−−−√4≈1.4542,c1=411.5+11.4142+11.3333+11.5811≈1.4512,d1=1.52+1.41422+1.33332+1.581124−−−−−−−−−−−−−−−−−−−−−−−−−−−−√≈1.4601.
1.45568889
Herausforderung
Berechnen Sie bei zwei positiven reellen Zahlen und ( ) ihren Mittelwert .aba<bMM(a,b)
Testfälle
1 1 => 1
1 2 => 1.45568889
100 200 => 145.568889
2.71 3.14 => 2.92103713
0.57 1.78 => 1.0848205
1.61 2.41 => 1.98965438
0.01 100 => 6.7483058
Anmerkungen
- Ihr Programm ist gültig, wenn die Differenz zwischen seiner Ausgabe und der korrekten Ausgabe nicht größer als 1/100000 des absoluten Wertes der Differenz zwischen den Eingabezahlen ist.
- Die Ausgabe sollte eine einzelne Zahl sein.
Das ist Code-Golf , also gewinnt der kürzeste Code!
Antworten:
Wolfram Language (Mathematica) , 52 Byte
Probieren Sie es online!
In meinem ersten Ansatz habe ich diese eingebauten
Mean
GeometricMean
HarmonicMean
und verwendetRootMeanSquare
Hier sind einige Ersetzungen zum Speichern von Bytes
HarmonicMean
->1/Mean[1/x]
von @Robin Ryder (3 Bytes gespeichert)GeometricMean
->E^Mean@Log@x
von @A. Rex (2 Bytes gespeichert)RootMeanSquare
->Mean[x^2]^.5
von @A. Rex (4 Bytes gespeichert)schließlich können wir zuweisen
Mean
zuM
(wie von @ovs vorgeschlagen) und speichern 5 mehr Bytesquelle
#//.x_:>N@{Mean@x,E^Mean@Log@x,1/Mean[1/x],Mean[x^2]^.5}&
R
706967 BytesProbieren Sie es online!
-1 Byte bei besserer Konditionierung.
-2 Bytes durch Umschalten auf Basis 2.
Wie bei einigen anderen Antworten wird der Ausdruck des geometrischen Mittels als arithmetisches Mittel auf der logarithmischen Skala (hier in Basis 2) verwendet:M0(x1,…,xn)=2M1(log2x1,…,log2xn).
Es wird auch die Tatsache verwendet , dass , dh . Die Bedingung ist daher äquivalent zu , was ich in der while-Schleife verwende; Dies wird erreicht, indem die Syntax missbraucht wird, die nur das erste Element berücksichtigt, wenn die Bedingung ein Vektor ist, daher die Reihenfolge, in der die Mittel gespeichert sind. (Beachten Sie, dass wir stattdessen auch verwenden da dies das Minimum der vier ist, aber wir könnten in der Bedingung nicht oder .)∀k,dk≥ak≥bk≥ck dk=max(ak,bk,ck,dk) ak=bk=ck=dk dk=M1(ak,bk,ck,dk) ck ak bk
while
Wenn wir die while-Schleife verlassen,
x
ist dies ein konstanter Vektor. Das Finale?x
berechnet seinen Mittelwert, um ihn auf einen Skalar zu reduzieren.quelle
J , 34 Bytes
(31 als Ausdruck ohne Zuweisung zur Variablen
f
)Probieren Sie es online!
Für Funktionen ,
a
undb
,a &.: b
( "a unter b" ( verwandte Herausforderung )) entspricht(b inv) a b
- gelten b, dann a, dann Inverse von b. In diesem Fall ist der geometrische / harmonische / quadratische Mittelwert der arithmetische Mittelwert "unter" Logarithmus, Inversion bzw. Quadrat.quelle
TI-BASIC,
423534 Bytes-1 Byte dank @SolomonUcko
Die Eingabe ist eine Liste von zwei Ganzzahlen in
Ans
.Die Ausgabe wird in gespeichert
Ans
und nach Abschluss des Programms automatisch ausgedruckt.Formeln, die für geometrische, harmonische und quadratische Mittel verwendet werden, basieren auf der Erklärung von user202729 .
Beispiel:
Erläuterung:
(Zeilenumbrüche wurden zur Verdeutlichung hinzugefügt. Sie erscheinen NICHT im Code.)
Anmerkungen:
TI-BASIC ist eine Token-Sprache. Die Anzahl der Zeichen entspricht nicht der Anzahl der Bytes.
e^(
ist dieses Ein-Byte-Token.^-1
wird für dieses Ein-Byte-Token verwendet.Ich habe mich
^-1
stattdessen für das Schreiben entschieden, weil das Token so aussieht,ֿ¹
als ob es sich in einem Codeblock befindet.√(
ist dieses Ein-Byte-Token.ΔList(
ist dieses Zwei-Byte-Token.quelle
max(DeltaList(Ans
->variance(Ans
.Java 10,
234229214211215206203196180177 Bytes-5 Bytes dank @PeterCordes .
-15 weitere Bytes dank @PeterCordes , inspiriert von der R-Antwort von @RobinRyder .
+4 Byte, da ich davon ausgegangen bin, dass die Eingänge vorbestellt sind.
-27 Bytes dank @ OlivierGrégoire .
Probieren Sie es online aus.
Erläuterung:
quelle
f+=Math.abs(d-D)<1e-9;
eine implizite Konvertierung von einem booleschen Vergleichsergebnis in eine 0/1-Ganzzahl erhalten und danndouble
. Hat Java eine kompakte Syntax dafür? Oder ist es möglich, zuf+=Math.abs(d-D)
überprüfen, ob die Summe der absoluten Differenzen klein genug ist?f>1e-8
als Schleifenbedingung: 229 Bytes.a->{for(double f=1,D,A[],l;f>1e-8;a=A){D=a[0];A=new double[]{f=0,1,0,0};for(var d:a){f+=Math.abs(d-D);A[0]+=d;A[1]*=d;A[2]+=1/d;A[3]+=d*d;}A[0]/=l=a.length;A[1]=Math.pow(A[1],1/l);A[2]=l/A[2];A[3]=Math.sqrt(A[3]/l);}return a[0];}
. Mit1e-9
läuft es langsamer (ungefähr doppelt so lange wie die CPU-Zeit) und muss mehr Iterationen ausführen, um im Wesentlichen 4 *d-D
so klein zu machen. Mit1e-7
ist es ungefähr die gleiche Geschwindigkeit wie 1e-8. Mit1e-6
unterscheiden sich einige der nachfolgenden Ziffern für einen Fall.f
ganz aufgeben und nur nachprüfena[3]-a[2]<4e-9
.l==2||
du meinst (Golfenl<3|
). Aber ja, guter Punkt; Ich habe es hinzugefügt. :)Kohle , 40 Bytes
Probieren Sie es online! Link ist eine ausführliche Version des Codes. Nimmt die Eingabe als Array von Zahlen. Erläuterung:
Wiederholen, während das Array verschiedene Werte enthält ...
... ersetzen Sie das Array durch eine Liste von Werten:
... die meine ...
... das geometrische Mittel ...
... das harmonische Mittel ...
... und das quadratische Mittel.
Konvertieren Sie ein Element des Arrays in einen String und drucken Sie es implizit aus.
quelle
Gelee , 24 Bytes
Probieren Sie es online!
quelle
PowerShell ,
182180183 ByteProbieren Sie es online!
quelle
05AB1E ,
262423 BytesProbieren Sie es online aus oder sehen Sie sich die Schritte aller Testfälle an .
-1 Byte dank @Grimy .
23-Byte-Alternative für geometrisches Mittel:
Probieren Sie es online aus oder sehen Sie sich die Schritte aller Testfälle an .
Erläuterung:
quelle
Δ©P®gzm®ÅA®zÅAz®nÅAt)}н
Y
für 2/4 zu verwenden. :)Δ©ÅA®.²ÅAo®zÅAz®nÅAt)}н
. Leider sieht es nicht so aus, als könnten wir all diese Dinge umgestaltenÅA
.Jelly ,
2524 BytesProbieren Sie es online!
Erläuterung
quelle
P*İL
für den geometrischen Mittelwert funktionieren?P*Lİ$
, würde also keine Bytes sparen. Es würde bedeuten, dass ichÆm
eine Zeile zurücksetzen könnte, ohne Byte zu kosten, aber ich mag die Tatsache, dass jeder momentan ein arithmetisches Mittel in seinem Kern hat.Python 3 , 152 Bytes
Probieren Sie es online!
Rekursive Funktion
f
, konvergiert zur Gleitkommapräzision. Funktioniert im Prinzip für alle Listen mit positiven Zahlen beliebiger Größe, ist jedoch durch diePython-Rekursion begrenzt und begrenzteinen Rundungsfehler für einige Testfälle.Alternativ können Sie sich für eine Genauigkeit von 9 Dezimalstellen entscheiden:
Python 3 , 169 Bytes
Probieren Sie es online!
quelle
C # 173 Bytes
Probieren Sie es online!
quelle
using System
undusing System.Linq
in Ihre Byteanzahl aufnehmen, da diese für die Ausführung des Programms erforderlich sind. Sie können Ihren Compiler in den C # Visual Interactive Compiler ändern, für den diese Importe nicht erforderlich sind. Auch1.0
->1d
Sauber , 124 Bytes
Probieren Sie es online!
Führt den Vorgang aus, bis sich das Ergebnis nicht mehr ändert.
Hurra für Gleitkommazahlen mit begrenzter Präzision!
quelle
Pyth, 32 Bytes
Versuchen Sie es online hier oder überprüfen alle die Testfälle (Balken zwei, siehe Anmerkung unten) auf einmal hier . Akzeptiert Eingaben als Liste.
Es scheint einige Rundungsprobleme zu geben, da bestimmte Eingaben nicht richtig konvergieren, wenn dies ansonsten der Fall sein sollte. Insbesondere
0.01 100
bleibt der Testfall bei Werten stecken[6.748305820749738, 6.748305820749738, 6.748305820749739, 6.748305820749738]
, und der Testfall1.61 2.41
bleibt stecken[1.9896543776640825, 1.9896543776640825, 1.9896543776640827, 1.9896543776640825]
- beachten Sie in beiden Fällen, dass sich der 3. Mittelwert (harmonischer Mittelwert) von den anderen unterscheidet.Ich bin nicht sicher, ob dieses Problem meine Eingabe ungültig macht, aber ich poste es trotzdem, wie es funktionieren sollte . Wenn dies nicht akzeptabel ist, kann es behoben werden, indem
.RRT
vor dem angegeben[
wird, dass jedes Mittel auf 10 Dezimalstellen gerundet werden soll, wie in dieser Testsuite dargestellt .quelle
.Wt{H
mitu
für -4 Bytes (und ÄnderungZ
anG
)Japt v2.0a0
-g
,4238 BytesEs muss einen kürzeren Weg geben ... Das ist eine Monstrosität! 4 Bytes gespart dank @Shaggy!
Versuch es
quelle
C # (Visual C # Interactive Compiler) , 177 Byte
Vielen Dank an @KevinCruijjsen für den Hinweis, dass die Verwendung der Gleitkommapräzision Probleme verursacht hat! Wäre 163 Bytes, wenn Doppelte absolut präzise wären.
Probieren Sie es online!
quelle
StackOverflowException
aufgrund der Gleitkommapräzision eine. Anstelle vonc==g[0]
dir könntest du sowas machenMath.Abs(c-g[0])<1e-9
. Probieren Sie es online aus.x86-Maschinencode (SIMD 4x Float mit 128-Bit-SSE1 und AVX) 94 Byte
x86-Maschinencode (SIMD 4x Double mit 256-Bit-AVX) 123 Byte
float
Besteht die Testfälle in der Frage, aber mit einer Loop-Exit-Schwelle, die klein genug ist, um dies zu ermöglichen, kann es leicht passieren, dass der Benutzer in einer Endlosschleife mit zufälligen Eingaben steckt.SSE1-Befehle mit einfacher Genauigkeit sind 3 Byte lang, SSE2- und einfache AVX-Befehle 4 Byte. (Skalar-Einzelanweisungen wie
sqrtss
sind auch 4 Byte lang, weshalb ich sie verwendesqrtps
, obwohl mir nur das niedrige Element am Herzen liegt. Es ist nicht einmal langsamer als sqrtss auf moderner Hardware). Ich habe AVX als zerstörungsfreies Ziel verwendet, um 2 Bytes gegenüber movaps + op zu sparen.In der doppelten Version können wir immer noch ein paar
movlhps
64-Bit-Blöcke kopieren (da uns oft nur das niedrige Element einer horizontalen Summe wichtig ist). Die horizontale Summe eines 256-Bit-SIMD-Vektors erfordert auch ein Extravextractf128
, um die hohe Hälfte zu erhalten, im Vergleich zu der langsamen, aber kleinen 2x-haddps
Strategie für das Floaten . Dasdouble
Version benötigt auch 2x 8-Byte-Konstanten anstelle von 2x 4-Byte. Insgesamt kommt es bei knapp 4/3 der Größe derfloat
Version heraus.mean(a,b) = mean(a,a,b,b)
für alle 4 dieser Mittel können wir also einfach die Eingabe auf 4 Elemente duplizieren und müssen nie length = 2 implementieren. So können wir zum Beispiel den geometrischen Mittelwert als 4th-root = sqrt (sqrt) fest codieren. Und wir brauchen nur eine FP - Konstante4.0
.Wir haben einen einzigen SIMD-Vektor von allen 4
[a_i, b_i, c_i, d_i]
. Daraus berechnen wir die 4 Mittelwerte als Skalare in separaten Registern und mischen sie für die nächste Iteration wieder zusammen. (Horizontale Operationen an SIMD-Vektoren sind unpraktisch, aber wir müssen das Gleiche für alle 4 Elemente in genügend Fällen tun, damit es ausgeglichen wird. Ich habe mit einer x87-Version davon begonnen, aber es wurde sehr lang und machte keinen Spaß.)Die Schleifenausgangsbedingung
}while(quadratic - harmonic > 4e-5)
(oder eine kleinere Konstante fürdouble
) basiert auf @ RobinRyders R-Antwort und Kevin Cruijssens Java-Antwort : Der quadratische Mittelwert ist immer die größte und der harmonische Mittelwert ist immer die kleinste (ohne Berücksichtigung von Rundungsfehlern). So können wir das Delta zwischen diesen beiden prüfen, um Konvergenz zu erkennen. Wir geben das arithmetische Mittel als skalares Ergebnis zurück. Sie liegt normalerweise zwischen diesen beiden Werten und ist wahrscheinlich am wenigsten anfällig für Rundungsfehler.Float-Version : Aufrufbar wie
float meanmean_float_avx(__m128);
bei arg und Rückgabewert in xmm0. (Also x86-64 System V oder Windows x64 vectorcall, aber nicht x64 fastcall.) Oder deklarieren Sie den Rückgabetyp so,__m128
dass Sie den quadratischen und harmonischen Mittelwert zum Testen erhalten.float
Es würde 1 zusätzliches Byte kosten, wenn dies 2 separate Argumente in xmm0 und xmm1 annehmen würde: Wir müssten einshufps
mit einem imm8 (anstatt nurunpcklps xmm0,xmm0
) zusammenmischen und 2 Eingaben duplizieren.(NASM-Auflistung erstellt mit
nasm -felf64 mean-mean.asm -l/dev/stdout | cut -b -34,$((34+6))-
. Entfernen Sie den Auflistungsteil und stellen Sie die Quelle mit wieder her.cut -b 34- > mean-mean.asm
)SIMD horizontale Summe und Division durch 4 (dh arithmetisches Mittel) wird in einer separaten Funktion implementiert, die wir
call
(mit einem Funktionszeiger zum Amortisieren der Kosten der Adresse) verwenden. Mit4/x
vorher / nachher oderx^2
vorher und nachher erhalten wir den harmonischen Mittelwert und den quadratischen Mittelwert. (Es war schmerzhaft, diesediv
Anweisungen zu schreiben , anstatt sie mit einer genau darstellbaren Zahl zu multiplizieren0.25
.)Der geometrische Mittelwert wird separat mit multiplizieren und verkettetem sqrt implementiert. Oder mit einem Quadrat zuerst, um die Größe des Exponenten zu verringern und möglicherweise die numerische Genauigkeit zu verbessern. log ist nicht verfügbar, nur
floor(log2(x))
über AVX512vgetexpps/pd
. Exp ist irgendwie über AVX512ER verfügbar (nur Xeon Phi), aber nur mit einer Genauigkeit von 2 ^ -23.Das Mischen von 128-Bit-AVX-Anweisungen und Legacy-SSE ist kein Leistungsproblem. Das Mischen von 256-Bit-AVX mit Legacy-SSE kann in Haswell erfolgen, aber in Skylake kann dies möglicherweise zu einer falschen Abhängigkeit für SSE-Anweisungen führen. Ich denke, meine
double
Version vermeidet unnötige Loop-Carraged-Dep-Ketten und Engpässe bei der div / sqrt-Latenz / dem Durchsatz.Doppelversion:
C-Testkabel
Bauen mit:
Natürlich benötigen Sie eine CPU mit AVX-Unterstützung oder einen Emulator wie Intel SDE. Verwenden Sie
-march=sandybridge
oder, um auf einem Host ohne native AVX-Unterstützung zu kompilieren-mavx
Ausführen: Besteht die hartcodierten Testfälle, aber bei der Float-Version
(b-a)/10000
überschreiten zufällige Testfälle häufig den in der Frage festgelegten Schwellenwert.FP-Fehler reichen aus, damit der Quad-Harm bei einigen Eingängen kleiner als Null ist.
Oder mit
a += 1<<11; b += (1<<12)+1;
unkommentierten:Keines dieser Probleme passiert mit
double
. Kommentieren Sieprintf
vor jedem Test aus, um festzustellen, dass der Ausgang leer ist (nichts aus demif(delta too high)
Block).TODO: Verwenden Sie die
double
Version als Referenz für diefloat
Version, anstatt nur zu betrachten, wie sie mit Quad-Harm konvergieren.quelle
Javascript - 186 Bytes
Nimmt die Eingabe als Array von Zahlen. Verwendet die mittleren Transformationen in der Antwort von J42161217 , um den Code zu verkürzen.
Probieren Sie es online
Erläuterung
quelle
Perl 5 ,
9272 BytesProbieren Sie es online!
... mit ein paar schmutzigen Tricks.
quelle
SNOBOL4 (CSNOBOL4) , 296 Bytes
Probieren Sie es online!
Einfache Implementierung. Benutzt einen Trick von meiner Antwort auf eine verwandte Frage, um ein bisschen mehr Golf zu spielen.
quelle