disclaimer: la moyenne est composée par moi
Définissez la moyenne arithmétique de nombres sous la forme
Définissez la moyenne géométrique de nombres sous la forme
Définissez la moyenne harmonique de nombres comme
M _ {- 1} (x_1, ..., x_n) = \ frac {n} {\ frac {1 } {x_2} + \ frac {1} {x_2} + ... + \ frac {1} {x_n}}
Définissez la moyenne quadratique de n nombres comme
M_2 (x_1, ..., x_n) = \ root \ of {\ frac {x_1 ^ 2 + x_2 ^ 2 + ... + x_n ^ 2} {n}}
La moyenne ( M_M ) est définie comme suit: Définissez quatre séquences ( a_k, b_k, c_k, d_knM1( x1, . . . ,xn) =x1+x2+ . . . +xnn
nM0( x1, . . . , xn) = x1X2. . . Xn--------√n
nM- 1( x1, . . . , xn) = n1X2+ 1X2+ . . . + 1Xn
nM2( x1, . . . , xn) = x21+ x22+ . . . + x2nn--------------√
MMunek, bk, ck, dk ) commeune0= M1( x1, . . . , xn) ,b0= M0( x1, . . . , xn) ,c0= M- 1( x1, . . . , xn) ,ré0= M2( x1, . . . , xn) ,unek + 1= M1( unk, bk, ck, dk) ,bk + 1= M0( unk, bk, ck, dk) ,ck + 1= M- 1( unk, bk, ck, dk) ,rék + 1= M2( unk, bk, ck, dk)
Les quatre séquences convergent vers le même nombre,MM( x1, x2, . . . , xn) .
Exemple
La moyenne moyenne de 1 et 2 est calculée comme suit: commencez par
Alors
Le calcul ultérieur des séquences doit être clair. On peut voir qu'ils convergent vers le même nombre, environ 1,45568889 .a0=(1+2)/2=1.5,b0=1∗2−−−−√=2–√≈1.4142,c0=211+12=43≈1.3333,d0=12+222−−−−−−−√=52−−√≈1.5811.
a1=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
Défi
Étant donné deux nombres réels positifs, et ( ), calculez leur moyenne moyenneune ba < bMM( a , b ) .
Cas de test
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
Remarques
- Votre programme est valide si la différence entre sa sortie et la sortie correcte n’est pas supérieure à 1/100000 de la valeur absolue de la différence entre les nombres saisis.
- La sortie devrait être un nombre unique.
C'est du code-golf , alors le code le plus court gagne!
Réponses:
Wolfram Language (Mathematica) , 52 octets
Essayez-le en ligne!
Dans ma première approche, j’ai utilisé ces commandes intégrées
Mean
GeometricMean
HarmonicMean
etRootMeanSquare
Voici quelques substitutions pour économiser des octets
HarmonicMean
->1/Mean[1/x]
par @Robin Ryder (3 octets enregistrés)GeometricMean
->E^Mean@Log@x
par @A. Rex (2 octets enregistrés)RootMeanSquare
->Mean[x^2]^.5
par @A. Rex (4 octets enregistrés)Enfin, nous pouvons affecter
Mean
àM
(comme proposé par @ovs) et économiser 5 octets supplémentaires.la source
#//.x_:>N@{Mean@x,E^Mean@Log@x,1/Mean[1/x],Mean[x^2]^.5}&
R,
706967 octetsEssayez-le en ligne!
-1 octet avec un meilleur conditionnement.
-2 octets en basculant en base 2.
Comme d'autres réponses, celui - ci utilise l'expression de la moyenne géométrique comme une moyenne arithmétique sur l'échelle logarithmique (ici en base 2):M0( x1, … , Xn) = 2M1( log2X1, … , Connectez-vous2Xn).
Il utilise également le fait que∀ k , dk≥ ak≥ bk≥ ck , c’est-à-dire rék= max ( ak, bk, ck, dk) . La condition unek= bk= ck= dk est donc équivalente à rék= M1( unk, bk, ck, dk) , qui est ce queutilise dans la boucle tandis que; ceci est réalisé en abusant de la syntaxeck car c'est le minimum des quatre, mais nous ne pourrions pas utiliserunek ou unbk dans la condition.)
while
dont ne prend en compte que le premier élément lorsque la condition est un vecteur, d'où l'ordre dans lequel les moyens sont stockés. (Notez que nous pourrions aussi utiliserLorsque nous sortons de la boucle while,
x
est un vecteur constant. La finale?x
calcule sa moyenne pour le réduire à un scalaire.la source
J , 34 octets
(31 en tant qu'expression sans l'affectation de variable
f
)Essayez-le en ligne!
Pour les fonctions
a
etb
,a &.: b
("un sous b" ( défi lié )) équivaut à(b inv) a b
- appliquer b, puis a, puis l'inverse de b. Dans ce cas, la moyenne géométrique / harmonique / quadratique est la moyenne arithmétique "sous" logarithme, inversion et carré, respectivement.la source
TI-BASIC,
423534 octets-1 octet grâce à @SolomonUcko
L'entrée est une liste de deux entiers dans
Ans
.La sortie est stockée dans
Ans
et est automatiquement imprimée à la fin du programme.Les formules utilisées pour les moyennes géométriques, harmoniques et quadratiques sont basées sur l'explication de user202729 .
Exemple:
Explication:
(des nouvelles lignes ont été ajoutées à des fins de clarification. Elles n'apparaissent pas dans le code.)
Remarques:
TI-BASIC est un langage à jeton. Le nombre de caractères ne correspond pas au nombre d'octets.
e^(
est ce jeton d'un octet.^-1
est utilisé pour ce jeton d'un octet.J'ai opté pour l'écriture
^-1
car le jeton ressembleֿ¹
à un bloc de code.√(
est ce jeton d'un octet.ΔList(
est ce jeton de deux octets.la source
max(DeltaList(Ans
->variance(Ans
.Java 10,
234229214211215206203196 196180177 octets-5 octets grâce à @PeterCordes .
-15 octets supplémentaires grâce à @PeterCordes , inspiré de la réponse R de @RobinRyder .
+4 octets parce que j'ai supposé que les entrées sont pré-commandées.
-27 octets grâce à @ OlivierGrégoire .
Essayez-le en ligne.
Explication:
la source
f+=Math.abs(d-D)<1e-9;
obtenir une conversion implicite d'un résultat de comparaison booléen en un entier 0/1, puisdouble
. Java a-t-il une syntaxe compacte pour cela? Ou est-il possible de le fairef+=Math.abs(d-D)
et de vérifier ensuite que la somme des différences absolues est suffisamment petite ?f>1e-8
fonctionne comme une condition de boucle: 229 octets.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];}
. Avec1e-9
, il est plus lent (environ deux fois le temps de calcul), obligé de faire plus d’itérations pour obtenir essentiellement 4 *d-D
aussi petit. Avec1e-7
, c'est à peu près la même vitesse que 1e-8. Avec1e-6
, certains des derniers chiffres diffèrent d’un cas à l’autre.f
entièrement et vérifier uniquementa[3]-a[2]<4e-9
.l==2||
vous voulez dire ( joué au golfl<3|
). Mais oui, bon point; Je l'ai ajouté. :)Charbon de bois , 40 octets
Essayez-le en ligne! Le lien est vers la version verbeuse du code. Prend les entrées sous forme de tableau de nombres. Explication:
Répétez l'opération tant que le tableau contient différentes valeurs ...
... remplace le tableau par une liste de valeurs:
... la moyenne...
... la moyenne géométrique ...
... le moyen harmonique ...
... et la racine signifie carré.
Convertit un élément du tableau en chaîne et l'imprime implicitement.
la source
Gelée , 24 octets
Essayez-le en ligne!
la source
PowerShell ,
182180183 octetsEssayez-le en ligne!
la source
05AB1E ,
262423 octetsEssayez-le en ligne ou voyez les étapes de tous les cas de test .
-1 octet grâce à @Grimy .
Alternative de 23 octets pour la moyenne géométrique:
Essayez-le en ligne ou consultez les étapes de tous les cas de test .
Explication:
la source
Δ©P®gzm®ÅA®zÅAz®nÅAt)}н
Y
2/4. :)Δ©ÅA®.²ÅAo®zÅAz®nÅAt)}н
. Malheureusement, il ne semble pas que nous puissions refactoriser tous cesÅA
problèmes.Gelée ,
25 à24 octetsEssayez-le en ligne!
Explication
la source
P*İL
fonctionner pour la moyenne géométrique?P*Lİ$
ne pas économiser des octets? Cela voudrait dire que je pourrais ramenerÆm
une ligne sans chiffrer d'octets, mais j'aime bien le fait que chacune d'entre elles a actuellement une moyenne arithmétique.Python 3 , 152 octets
Essayez-le en ligne!
Fonction récursive
f
, convergera vers la précision en virgule flottante. Fonctionne en principe pour toutes les listes de nombres positifs de toute taille, mais est limitée parla récursivité de Python, limitant l’erreur d’arrondi pour certains cas de test.Vous pouvez également choisir une précision de 9 décimales:
Python 3 , 169 octets
Essayez-le en ligne!
la source
C # , 173 octets
Essayez-le en ligne!
la source
using System
etusing System.Linq
dans votre nombre d'octets, car ils sont nécessaires à l'exécution du programme. Vous pouvez remplacer votre compilateur par le compilateur C # Visual Interactive, qui n'a pas besoin de ces importations. Aussi,1.0
->1d
Propre , 124 octets
Essayez-le en ligne!
Effectue l'opération jusqu'à ce que le résultat cesse de changer.
Vive la virgule flottante de précision limitée!
la source
Pyth, 32 octets
Essayez-le en ligne ici , ou vérifiez tous les cas de test (sauf deux, voir la note ci-dessous) à la fois ici . Accepte les entrées sous forme de liste.
Il semble y avoir quelques problèmes d'arrondi, car certaines entrées ne convergent pas correctement lorsqu'elles le devraient autrement. En particulier, le scénario de test
0.01 100
reste bloqué aux valeurs[6.748305820749738, 6.748305820749738, 6.748305820749739, 6.748305820749738]
et le scénario de test1.61 2.41
reste bloqué à[1.9896543776640825, 1.9896543776640825, 1.9896543776640827, 1.9896543776640825]
- notez dans les deux cas que la 3ème moyenne (moyenne harmonique) diffère des autres.Je ne sais pas si ce problème invalide mon inscription, mais je le publie quand même, car cela devrait fonctionner. Si cela n’est pas acceptable, vous pouvez résoudre ce problème en procédant
.RRT
avant le[
, en arrondissant chacun des moyennes à 10 décimales, comme indiqué dans cette suite de tests .la source
.Wt{H
paru
-4 octets (et le remplacerZ
parG
)Japt v2.0a0
-g
,4238 octetsIl doit y avoir un moyen plus court ... C'est une monstruosité! Sauvegardé 4 octets grâce à @Shaggy!
L'essayer
la source
C # (compilateur interactif Visual C #) , 177 octets
Merci à @KevinCruijjsen d'avoir signalé que l'utilisation de la précision en virgule flottante posait problème! Ce serait 163 octets si les doubles étaient parfaitement précis.
Essayez-le en ligne!
la source
StackOverflowException
précision due à la virgule flottante. Au lieu dec==g[0]
vous pourrait faire quelque chose commeMath.Abs(c-g[0])<1e-9
. Essayez-le en ligne.Code machine x86 (SIMD 4x float utilisant SSE1 et AVX 128 bits) 94 octets
Code machine x86 (SIMD 4x double utilisant AVX 256 bits) 123 octets
float
réussit les tests dans la question, mais avec un seuil de sortie de boucle suffisamment petit pour que cela se produise, il est facile pour lui de rester bloqué dans une boucle infinie avec des entrées aléatoires.Les instructions SSE1 avec une seule précision empaquetée ont une longueur de 3 octets, mais les instructions SSE2 et AVX simples ont une longueur de 4 octets. (Les instructions Scalar-single, par exemple,
sqrtss
ont également une longueur de 4 octets, c'est pourquoi je l'utilisesqrtps
même si je ne me soucie que de l'élément low. Ce n'est même pas plus lent que sqrtss sur du matériel moderne). J'ai utilisé AVX pour une destination non destructive pour économiser 2 octets contre movaps + op.Dans la version double, nous pouvons toujours faire un couple
movlhps
pour copier des morceaux de 64 bits (car souvent, nous ne nous soucions que de l'élément bas d'une somme horizontale). La somme horizontale d'un vecteur SIMD 256 bits nécessite également un extravextractf128
pour obtenir la moitié haute, par rapport à la stratégie 2x lente mais lentehaddps
pour float . ledouble
version 2x nécessite également des constantes 2x à 8 octets, au lieu de 2x à 4 octets. Globalement, il arrive à près de 4/3 de la taille de lafloat
version.mean(a,b) = mean(a,a,b,b)
pour tous les 4 de ces moyens , nous pouvons donc simplement dupliquer l'entrée jusqu'à 4 éléments et ne jamais avoir à mettre en œuvre length = 2. Ainsi, nous pouvons coder en dur une moyenne géométrique telle que 4th-root = sqrt (sqrt), par exemple. Et nous avons seulement besoin d' une constante FP,4.0
.Nous avons un seul vecteur SIMD sur 4
[a_i, b_i, c_i, d_i]
. À partir de cela, nous calculons les 4 moyennes sous forme de scalaires dans des registres séparés, puis nous les remettons ensemble pour la prochaine itération. (Les opérations horizontales sur les vecteurs SIMD ne sont pas pratiques, mais nous devons faire la même chose pour les 4 éléments dans un nombre suffisant de cas. Cela a été équilibré. J'ai commencé avec une version x87 de ce logiciel, mais cela devenait très long et amusant.)La condition boucle sortie
}while(quadratic - harmonic > 4e-5)
(ou une plus petite constantedouble
) est basée sur @ de RobinRyder réponse R et la réponse Java Kevin Cruijssen : moyenne quadratique est toujours la plus grande amplitude et moyenne harmonique est toujours la plus petite (abstraction faite des erreurs d' arrondi). Donc, nous pouvons vérifier le delta entre ces deux pour détecter la convergence. Nous renvoyons la moyenne arithmétique en tant que résultat scalaire. C'est généralement entre ces deux et est probablement le moins susceptible d'erreurs d'arrondi.Version float : appelable comme
float meanmean_float_avx(__m128);
avec les arguments arg et return en xmm0. (Donc, x86-64 System V, ou Windows x64 vectorcall, mais pas x64 fastcall.) Ou déclarez le type de retour__m128
afin que vous puissiez obtenir la moyenne quadratique et harmonique pour le test.Laisser cela prendre 2
float
arguments distincts dans xmm0 et xmm1 coûterait un octet supplémentaire: il nous faudrait unshufps
avec un imm8 (au lieu de simplementunpcklps xmm0,xmm0
) pour mélanger et dupliquer deux entrées.(Liste NASM créée avec
nasm -felf64 mean-mean.asm -l/dev/stdout | cut -b -34,$((34+6))-
. Supprimez la partie liste et récupérez le sourcecut -b 34- > mean-mean.asm
)SIMD La somme horizontale et la division par 4 (c'est-à-dire une moyenne arithmétique) sont implémentées dans une fonction distincte que nous
call
(avec un pointeur de fonction pour amortir le coût de l'adresse). Avec4/x
avant / après, oux^2
avant et après après, nous obtenons la moyenne harmonique et la moyenne quadratique. (Il était pénible d’écrire cesdiv
instructions au lieu de les multiplier par un exactement représentable0.25
.)La moyenne géométrique est mise en œuvre séparément avec multiplie et sqrt chaîné. Ou avec un premier carré pour réduire la magnitude des exposants et peut-être aider la précision numérique. le journal n'est pas disponible, uniquement
floor(log2(x))
via AVX512vgetexpps/pd
. Exp est en quelque sorte disponible via AVX512ER (Xeon Phi uniquement), mais avec une précision de 2 ^ -23 seulement.Le mélange d'instructions AVX 128 bits et de SSE hérité n'est pas un problème de performances. Le mélange d’AVX 256 bits et de SSE hérité peut s’effectuer sur Haswell, mais sur Skylake, cela crée potentiellement une fausse dépendance potentielle pour les instructions SSE. Je pense que ma
double
version évite les chaînes dep inutiles transportées en boucle, ainsi que les goulots d'étranglement sur la latence / le débit de div / sqrt.Version double:
Harnais de test C
Construire avec:
Évidemment, vous avez besoin d’un processeur prenant en charge AVX ou d’un émulateur comme Intel SDE. Pour compiler sur un hôte sans support natif d’AVX, utilisez
-march=sandybridge
ou-mavx
Exécuter: réussit les cas de test codés en dur, mais pour la version flottante, les cas de test aléatoires échouent souvent au
(b-a)/10000
seuil défini dans la question.Les erreurs de PF suffisent pour que quad-harm soit inférieur à zéro pour certaines entrées.
Ou sans
a += 1<<11; b += (1<<12)+1;
commentaire:Aucun de ces problèmes n'arrive avec
double
. Mettez en commentaire l'printf
avant chaque test pour vérifier que la sortie est vide (rien duif(delta too high)
bloc).TODO: utilisez la
double
version comme référence pour lafloat
version, au lieu de simplement regarder comment elles convergent avec quad-harm.la source
Javascript - 186 octets
Prend les entrées sous forme de tableau de nombres. Utilise les transformations moyennes dans la réponse de J42161217 pour raccourcir le code.
Essayez-le en ligne
Explication
la source
Perl 5 ,
9272 octetsEssayez-le en ligne!
... en utilisant des tours sales.
la source
SNOBOL4 (CSNOBOL4) , 296 octets
Essayez-le en ligne!
Mise en œuvre simple. Utilise un truc de ma réponse à une question liée au golf un peu plus.
la source