descargo de responsabilidad: la media es hecha por mí
Definir la media aritmética de n números como
M1(x1,...,xn)=x1+x2+...+xnn
Definir la media geométrica dennúmeros como
M0(x1,...,xn)=x1x2...xn−−−−−−−−√n
Definir la media armónica dennúmeros como
M−1(x1,...,xn)=n1x2+1x2+...+1xn
Definir la media cuadrática dennúmeros como
M2(x1,...,xn)=x21+x22+...+x2nn−−−−−−−−−−−−−−√
The Mean media (MM) se define como sigue: definir cuatro secuencias (ak,bk,ck,dk) comoa0=M1(x1,...,xn),b0=M0(x1,...,xn),c0=M−1(x1,...,xn),d0=M2(x1,...,xn),ak+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)
Todas las cuatro secuencias convergen para el mismo número,MM(x1,x2,...,xn) .
Ejemplo
La media media de 1 y 2 se calcula de la siguiente manera: comience con a0=(1+2)/2=1.5,b0=1∗2−−−−√=2–√≈1.4142,c0=211+12=43≈1.3333,d0=12+222−−−−−−−√=52−−√≈1.5811.
Entonces
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.
El cálculo adicional de las secuencias debe ser claro. Se puede ver que convergen al mismo número, aproximadamente1.45568889.
Reto
Dados dos números reales positivos, a y b ( a<b ), calcule su media media MM(a,b) .
Casos de prueba
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
Notas
- Su programa es válido si la diferencia entre su salida y la salida correcta no es mayor que 1/100000 del valor absoluto de la diferencia entre los números de entrada.
- La salida debe ser un solo número.
Este es el código de golf , por lo que gana el código más corto.
Respuestas:
Wolfram Language (Mathematica) , 52 bytes
Pruébalo en línea!
En mi primer acercamiento usé estos builtins
Mean
GeometricMean
HarmonicMean
yRootMeanSquare
Aquí hay algunas sustituciones para guardar bytes
HarmonicMean
->1/Mean[1/x]
por @Robin Ryder (3 bytes guardados)GeometricMean
->E^Mean@Log@x
por @A. Rex (2 bytes guardados)RootMeanSquare
->Mean[x^2]^.5
por @A. Rex (4 bytes guardados)finalmente podemos asignar
Mean
aM
(según lo propuesto por @ovs) y guardar 5 bytes másfuente
#//.x_:>N@{Mean@x,E^Mean@Log@x,1/Mean[1/x],Mean[x^2]^.5}&
R,
706967 bytesPruébalo en línea!
-1 byte con mejor acondicionamiento.
-2 bytes cambiando a la base 2.
while
Cuando salimos del ciclo while,
x
es un vector constante. El final?x
calcula su media para reducirlo a un escalar.fuente
J , 34 bytes
(31 como una expresión sin la asignación a variable
f
)Pruébalo en línea!
Para funciones
a
yb
,a &.: b
("a debajo de b" ( desafío relacionado )) es equivalente a(b inv) a b
- aplicar b, luego a, luego inverso de b. En este caso, la media geométrica / armónica / cuadrática es la media aritmética "debajo" del logaritmo, la inversión y el cuadrado, respectivamente.fuente
TI-BASIC,
423534 bytes-1 byte gracias a @SolomonUcko
La entrada es una lista de dos enteros en
Ans
.La salida se almacena en
Ans
y se imprime automáticamente cuando se completa el programa.Las fórmulas utilizadas para medios geométricos, armónicos y cuadráticos se basan en la explicación del usuario 202729 .
Ejemplo:
Explicación:
(Se han agregado nuevas líneas para aclaración. NO aparecen en el código).
Notas:
TI-BASIC es un lenguaje tokenizado. El recuento de caracteres no es igual al recuento de bytes.
e^(
es este token de un byte.^-1
se usa para este token de un byte.En su lugar, opté por escribir
^-1
porque el token se veֿ¹
cuando está en un bloque de código.√(
es este token de un byte.ΔList(
es este token de dos bytes.fuente
max(DeltaList(Ans
->variance(Ans
.Java 10,
234229214211215206203196180177 bytes-5 bytes gracias a @PeterCordes .
-15 bytes más gracias a @PeterCordes , inspirado en la respuesta R de @RobinRyder .
+4 bytes porque supuse que las entradas están pre ordenadas.
-27 bytes gracias a @ OlivierGrégoire .
Pruébalo en línea.
Explicación:
fuente
f+=Math.abs(d-D)<1e-9;
obtener una conversión implícita de un resultado de comparación booleano a un entero 0/1 y luegodouble
. ¿Java tiene alguna sintaxis compacta para eso? ¿O es posible hacerf+=Math.abs(d-D)
y luego verificar que la suma de las diferencias absolutas sea lo suficientemente pequeña ?f>1e-8
funciona como una condición de bucle: 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];}
. Con1e-9
, se ejecuta más lento (aproximadamente el doble del tiempo de CPU), teniendo que hacer más iteraciones para obtener esencialmente 4 *d-D
menos de ese tamaño. Con1e-7
, es aproximadamente la misma velocidad que 1e-8. Con1e-6
algunos de los dígitos finales difieren para un caso.f
completo y solo verificara[3]-a[2]<4e-9
.l==2||
te refieres (golfedl<3|
). Pero sí, buen punto; Lo he agregado :)Carbón , 40 bytes.
Pruébalo en línea! El enlace es a la versión detallada del código. Toma la entrada como una matriz de números. Explicación:
Repita mientras la matriz contiene diferentes valores ...
... reemplaza la matriz con una lista de valores:
... el significado...
... la media geométrica ...
... el significado armónico ...
... y la raíz del cuadrado medio.
Convierta un elemento de la matriz en una cadena e imprímalo implícitamente.
fuente
Jalea , 24 bytes
Pruébalo en línea!
fuente
PowerShell ,
182180183 bytesPruébalo en línea!
fuente
05AB1E ,
262423 bytesPruébelo en línea o vea los pasos de todos los casos de prueba .
-1 byte gracias a @Grimy .
Alternativa de 23 bytes para la media geométrica:
Pruébelo en línea o vea los pasos de todos los casos de prueba .
Explicación:
fuente
Δ©P®gzm®ÅA®zÅAz®nÅAt)}н
Y
2/4. :)Δ©ÅA®.²ÅAo®zÅAz®nÅAt)}н
. Desafortunadamente, no parece que podamos refactorizar todos esosÅA
s.Jalea ,
2524 bytesPruébalo en línea!
Explicación
fuente
P*İL
trabajo para la media geométrica?P*Lİ$
así que no guardaría bytes. Significaría que podríaÆm
volver a bajar una línea sin costar bytes, pero me gusta mucho el hecho de que cada uno tiene actualmente una media aritmética en su núcleo.Python 3 , 152 bytes
Pruébalo en línea!
La función recursiva
f
convergerá a la precisión de coma flotante. Funciona en principio para todas las listas de números positivos de cualquier tamaño, pero está limitado porel límite de recurrencia de Python,un error de redondeo para algunos casos de prueba.Alternativamente, conformarse con precisión de 9 decimales:
Python 3 , 169 bytes
Pruébalo en línea!
fuente
C # , 173 bytes
Pruébalo en línea!
fuente
using System
yusing System.Linq
en su recuento de bytes, ya que son necesarios para que el programa se ejecute. Puede cambiar su compilador al Compilador interactivo visual de C #, que no necesita esas importaciones. Además,1.0
->1d
Limpio , 124 bytes
Pruébalo en línea!
Realiza la operación hasta que el resultado deja de cambiar.
¡Hurra por la precisión limitada del punto flotante!
fuente
Pyth, 32 bytes
Pruébelo en línea aquí , o verifique todos los casos de prueba (barra dos, vea la nota a continuación) de una vez aquí . Acepta entradas como una lista.
Parece haber algunos problemas con el redondeo, ya que ciertas entradas no convergen correctamente cuando de lo contrario deberían. En particular, el caso de prueba
0.01 100
se atasca en los valores[6.748305820749738, 6.748305820749738, 6.748305820749739, 6.748305820749738]
, y el caso de prueba1.61 2.41
se atasca en[1.9896543776640825, 1.9896543776640825, 1.9896543776640827, 1.9896543776640825]
- observe en ambos casos que la tercera media (media armónica) difiere de las demás.No estoy seguro de si este problema invalida mi entrada, pero lo estoy publicando de todos modos, ya que debería funcionar. Si esto no es aceptable, se puede arreglar inscribiéndolo
.RRT
antes de[
, para redondear cada uno de los medios a 10 decimales, como se ve en este conjunto de pruebas .fuente
.Wt{H
conu
de -4 bytes (y el cambioZ
aG
)Japt v2.0a0
-g
,4238 bytesTiene que haber un camino más corto ... ¡Esto es una monstruosidad! ¡Guardado 4 bytes gracias a @Shaggy!
Intentalo
fuente
C # (compilador interactivo de Visual C #) , 177 bytes
¡Gracias a @KevinCruijjsen por señalar que usar la precisión de coma flotante estaba causando problemas! Sería 163 bytes si los dobles fueran perfectamente precisos.
Pruébalo en línea!
fuente
StackOverflowException
deben a la precisión de coma flotante. En lugar dec==g[0]
usted podría hacer algo asíMath.Abs(c-g[0])<1e-9
. Pruébalo en línea.Código de máquina x86 (SIMD 4x flotante usando SSE1 y AVX de 128 bits) 94 bytes
Código de máquina x86 (SIMD 4x doble con AVX de 256 bits) 123 bytes
float
pasa los casos de prueba en la pregunta, pero con un umbral de salida de bucle lo suficientemente pequeño como para que eso suceda, es fácil que se quede atascado en un bucle infinito con entradas aleatorias.Las instrucciones SSE1 de precisión simple empaquetada tienen 3 bytes de longitud, pero las instrucciones SSE2 y AVX simples tienen 4 bytes de longitud. (Las instrucciones simples escalares
sqrtss
también tienen una longitud de 4 bytes, por eso lo utilizosqrtps
aunque solo me importa el elemento bajo. Ni siquiera es más lento que sqrtss en el hardware moderno). Usé AVX para un destino no destructivo para guardar 2 bytes vs.movaps + op.En la versión doble todavía podemos hacer un par
movlhps
para copiar fragmentos de 64 bits (porque a menudo solo nos importa el elemento bajo de una suma horizontal). La suma horizontal de un vector SIMD de 256 bits también requiere un extravextractf128
para obtener la mitad alta, en comparación con la estrategia lenta pero pequeña de 2xhaddps
para flotación . losdouble
La versión también necesita 2x constantes de 8 bytes, en lugar de 2x 4 bytes. En general, sale cerca de 4/3 del tamaño de lafloat
versión.mean(a,b) = mean(a,a,b,b)
para los 4 de estos medios , por lo que simplemente podemos duplicar la entrada de hasta 4 elementos y nunca tener que implementar length = 2. Por lo tanto, podemos codificar la media geométrica como 4th-root = sqrt (sqrt), por ejemplo. Y sólo tenemos una constante FP,4.0
.Tenemos un solo vector SIMD de los 4
[a_i, b_i, c_i, d_i]
. A partir de eso, calculamos los 4 medios como escalares en registros separados y los volvemos a mezclar para la próxima iteración. (Las operaciones horizontales en los vectores SIMD son inconvenientes, pero necesitamos hacer lo mismo para los 4 elementos en suficientes casos que se equilibren. Comencé con una versión x87 de esto, pero se estaba haciendo muy larga y no era divertida).La condición de salida de bucle de
}while(quadratic - harmonic > 4e-5)
(o una constante menor paradouble
) se basa en la respuesta R de @ RobinRyder y la respuesta Java de Kevin Cruijssen : la media cuadrática es siempre la magnitud más grande y la media armónica es siempre la más pequeña (ignorando los errores de redondeo). Entonces podemos verificar el delta entre esos dos para detectar la convergencia. Devolvemos la media aritmética como el resultado escalar. Generalmente está entre esos dos y es probablemente el menos susceptible a los errores de redondeo.Versión flotante : invocable como
float meanmean_float_avx(__m128);
con el valor arg y return en xmm0. (Por lo tanto, x86-64 System V o Windows x64 vectorcall, pero no x64 fastcall). O declare el tipo de retorno__m128
para que pueda obtener la media cuadrática y armónica para la prueba.Dejar que esto tome 2
float
args separados en xmm0 y xmm1 costaría 1 byte adicional: necesitaríamos unshufps
con un imm8 (en lugar de solounpcklps xmm0,xmm0
) para mezclar y duplicar 2 entradas.(Listado NASM creado con
nasm -felf64 mean-mean.asm -l/dev/stdout | cut -b -34,$((34+6))-
. Elimine la parte del listado y recupere la fuente concut -b 34- > mean-mean.asm
)SIMD suma horizontal y dividir por 4 (es decir, media aritmética) se implementa en una función separada que nosotros
call
(con un puntero de función para amortizar el costo de la dirección). Con4/x
before / after, ox^2
before y sqrt after, obtenemos la media armónica y la media cuadrática. (Fue doloroso escribir estasdiv
instrucciones en lugar de multiplicarlo por uno exactamente representable0.25
).La media geométrica se implementa por separado con sqrt multiplicado y encadenado. O con un sqrt primero para reducir la magnitud del exponente y quizás ayudar a la precisión numérica. el registro no está disponible, solo a
floor(log2(x))
través de AVX512vgetexpps/pd
. Exp está disponible a través de AVX512ER (solo Xeon Phi), pero con solo 2 ^ -23 de precisión.Mezclar instrucciones AVX de 128 bits y SSE heredado no es un problema de rendimiento. Mezclar AVX de 256 bits con SSE heredado puede estar en Haswell, pero en Skylake simplemente crea una potencial dependencia falsa para las instrucciones de SSE. Creo que mi
double
versión evita cadenas dep innecesarias transportadas en bucle y cuellos de botella en la latencia / rendimiento div / sqrt.Versión doble:
Arnés de prueba C
Construir con:
Obviamente necesita una CPU con soporte AVX, o un emulador como Intel SDE. Para compilar en un host sin soporte AVX nativo, use
-march=sandybridge
o-mavx
Ejecutar: pasa los casos de prueba codificados, pero para la versión flotante, los casos de prueba aleatorios a menudo fallan el
(b-a)/10000
umbral establecido en la pregunta.Los errores de FP son suficientes para que el daño cuádruple sea menor que cero para algunas entradas.
O con sin
a += 1<<11; b += (1<<12)+1;
comentar:Ninguno de estos problemas ocurre
double
. Comenteprintf
antes de cada prueba para ver que la salida está vacía (nada delif(delta too high)
bloque).TODO: use la
double
versión como referencia para lafloat
versión, en lugar de solo mirar cómo convergen con quad-harm.fuente
Javascript - 186 bytes
Toma la entrada como una matriz de números. Utiliza las transformaciones medias en la respuesta de J42161217 para acortar el código.
Pruébalo en línea
Explicación
fuente
Perl 5 ,
9272 bytesPruébalo en línea!
... usando algunos trucos sucios.
fuente
SNOBOL4 (CSNOBOL4) , 296 bytes
Pruébalo en línea!
Implementación directa. Utiliza un truco de mi respuesta a una pregunta relacionada con el golf un poco más.
fuente