language agnostic - Código de golf: Número abreviado amistoso
language-agnostic code-golf (9)
Basado en esta pregunta: ¿Hay una manera de redondear los números en un formato amigable?
EL DESAFÍO - ACTUALIZADO! (eliminado cientos de abreviaturas de espec.)
El código más corto por número de caracteres que abreviará un entero (sin decimales).
El código debe incluir el programa completo.
El rango relevante es de 0 - 9,223,372,036,854,775,807
(el límite superior para el entero de 64 bits con signo).
El número de lugares decimales para la abreviatura será positivo. No tendrá que calcular lo siguiente: 920535 abbreviated -1 place
(que sería algo así como 0.920535M
).
Los números en el lugar de las decenas y centenas ( 0-999
) nunca deben abreviarse (la abreviatura de los lugares decimales número 57
a 1+
es 5.7dk
es 5.7dk
y no es amigable).
Recuerde redondear a la mitad de cero (23.5 se redondea a 24). El redondeo del banquero es verboten.
Aquí están las abreviaturas de números relevantes:
h = hundred (10
2
)
k = thousand (10
3
)
M = million (10
6
)
G = billion (10
9
)
T = trillion (10
12
)
P = quadrillion (10
15
)
E = quintillion (10
18
)
MUESTRA DE ENTRADAS / SALIDAS (las entradas se pueden pasar como argumentos separados):
El primer argumento será el entero a abreviar. El segundo es el número de decimales.
12 1 => 12 // tens and hundreds places are never rounded
1500 2 => 1.5k
1500 0 => 2k // look, ma! I round UP at .5
0 2 => 0
1234 0 => 1k
34567 2 => 34.57k
918395 1 => 918.4k
2134124 2 => 2.13M
47475782130 2 => 47.48G
9223372036854775807 3 => 9.223E
// ect...
Respuesta original de la pregunta relacionada (JavaScript, no sigue las especificaciones):
function abbrNum(number, decPlaces) {
// 2 decimal places => 100, 3 => 1000, etc
decPlaces = Math.pow(10,decPlaces);
// Enumerate number abbreviations
var abbrev = [ "k", "m", "b", "t" ];
// Go through the array backwards, so we do the largest first
for (var i=abbrev.length-1; i>=0; i--) {
// Convert array index to "1000", "1000000", etc
var size = Math.pow(10,(i+1)*3);
// If the number is bigger or equal do the abbreviation
if(size <= number) {
// Here, we multiply by decPlaces, round, and then divide by decPlaces.
// This gives us nice rounding to a particular decimal place.
number = Math.round(number*decPlaces/size)/decPlaces;
// Add the letter for the abbreviation
number += abbrev[i];
// We are done... stop
break;
}
}
return number;
}
Ruby - 79 77 75 83 caracteres
n,d=ARGV
l=n.to_s.length
printf"%.#{l>3?d:0}f%s",n.to_f/10**(l-l%3)," kMGTPE"[l/3]
Lee de los argumentos de la línea de comandos.
74 72 80 caracteres, imprime la salida entre comillas dobles
n,d=ARGV
l=n.to_s.length
p"%.#{l>3?d:0}f%s"%[n.to_f/10**(l-l%3)," kMGTPE"[l/3]]
66 74 caracteres, imprime ceros extra
n,d=ARGV
l=n.to_s.length
p"%.#{d}f%s"%[n.to_f/10**(l-l%3)," kMGTPE"[l/3]]
Basado en this solución, y en el código de muestra.
dc - 75 caracteres
A7 1:U77 2:U71 3:U84 4:U80 5:U69 6:U[3+r1-r]sJ?sddZd3~d0=Jrsp-Ar^ldk/nlp;UP
Usa Z
(número de dígitos) %3
para encontrar la unidad. La mayoría del código es para configurar la matriz de caracteres de las unidades, el código real es de 39 caracteres. La macro J
ajusta cuando %3
es igual a 0
, para evitar imprimir 0.918M
en la séptima. caso de prueba. No se redondea adecuadamente.
Si hablas dc
, siéntete libre de mejorarlo.
J, 61 63 65 caracteres
((j.&(1&{)":({.%&1e3{:));{&'' kMGTPE''@{.)(([:<.1e3^.{.),{:,{.)
Salida:
((j.&(1&{)":({.%&1e3{:));{&'' kMGTPE''@{.)(([:<.1e3^.{.),{:,{.) 1500 0
┌─┬─┐
│2│k│
└─┴─┘
((j.&(1&{)":({.%&1e3{:));{&'' kMGTPE''@{.)(([:<.1e3^.{.),{:,{.) 987654321987654321 4
┌────────┬─┐
│987.6543│P│
└────────┴─┘
(La razón por la que la salida está "encuadrada" es porque J no admite una lista que consta de varios tipos)
Explicación (de derecha a izquierda):
(([:<.1000^.{.),{:,{.)
Hacemos una nueva lista de 3 elementos, usando ,
para unir ([:<.1000^.{.)
(El <.
Base 1000 log ^.
registro del primer parámetro {.
. Nos unimos con el segundo parámetro {:
y luego el primer param {.
.
Así que después del primer bit, hemos transformado, por ejemplo, 12345 2
en 1 2 12345
((j.&(1&{)":({.%&1000{:));{&'' kMGTPE''@{.)
usa ;
para unir las dos mitades de la expresión en un cuadro para producir el resultado final.
La primera mitad es ((j.&(1&{)":({.%&1000{:))
que divide ( %
) el último número de entrada ( {:
((j.&(1&{)":({.%&1000{:))
por 1000, el primer número de veces. Luego establece el precisión ":
usando el segundo número en la lista de entrada ( 1&{
).
La segunda mitad {&'' kMGTPE''@{.
- esto usa el primer número para seleccionar ( {
) el carácter apropiado de la lista de abreviaturas indexadas en 0.
Javascript 114 caracteres
function m(n,d){p=M.pow
d=p(10,d)
i=7
while(i)(s=p(10,i--*3))<=n&&(n=M.round(n*d/s)/d+"kMGTPE"[i])
return n}
También 114 - Uso de spidermonkey - Entrada en STDIN
[n,d]=readline().split('' ''),x=n.length,p=Math.pow,d=p(10,d)
x-=x%3
print(Math.round(n*d/p(10,x))/d+" kMGTPE"[x/3])
104 - Función
function(a,b,c,d){
c=(''''+a).length;
d=Math.pow;
b=d(10,b);
return((a*b/d(10,c-=c%3))+.5|0)/b+'' kMGTPE''[c/3]
}
Lo que también se convierte en 99 si reemplaza el (''''+a)
con a
y promete solo pasar cadenas :)
Perl 114 111 104 caracteres
Mi primera entrada de código de golf!
Argumentos proporcionados a partir de la entrada estándar: perl fna.pl 918395 1
($n,$d)=@ARGV;
@n=$n=~/./g;
@s='' kMGTPE''=~/./g;
printf"%.".(@n>3?$d:0)."f%s",$n/(10**($#n-$#n%3)),$s[@n/3];
Salida:
918.4k
Versión sin golf (con explicación):
( $number, $dp ) = @ARGV; # Read in arguments from standard input
@digits = split //, $number; # Populate array of digits, use this to count
# how many digits are present
@suffix = split //, '' kMGTPE''; # Generate suffix array
$number/(10**($#n-$#n%3)); # Divide number by highest multiple of 3
$precision = @n>3 ? $dp : 0; # Determine number of decimal points to print
sprintf "%.".$precision."f%s", # "%.2f" prints to 2 dp, "%.0f" prints integer
$number, $suffix[@n/3];# Select appropriate suffix
Python 2.x, 78 caracteres
a=input()
i=0
while a>=1e3:a/=1e3;i+=1
print"%g"%round(a,input())+" kMGTPE"[i]
Esta versión ( 75 caracteres ) utiliza printf, que imprimirá ceros adicionales y sigue la regla de redondeo a par.
a=input()
i=0
while a>=1e3:a/=1e3;i+=1
print"%%.%df"%input()%a+" kMGTPE"[i]
Haskell, 126 (sin importar, es una función que toma dos argumentos):
f n p|l>3=showFFloat (Just p) (c n/c 10^(l-w)) [" kMGTPE"!!f]|True=show n where(f,w)=divMod l 3;c=fromIntegral;l=length$show n
Expandido:
import Numeric
doit :: Integer -> Int -> String
doit n p
| l > 3 = showFFloat (Just p) d [" kMGTPE" !! f]
| otherwise = show n
where
d = (fromIntegral n) / fromIntegral (10^(l-w))
(f,w) = divMod l 3
l = length $ show n
PHP 57 caracteres
for($a=num+1;$a>=1;$a=$a/26)$c=chr(--$a%26+65).$c;echo$c;
Perl 94 caracteres
($_,$d)=@ARGV;$l=length;@u='' kMGTPE''=~/./g;printf"%.".($l>3?$d:0)."f$u[$l/3]",$_/10**($l-$l%3)
Uso:
perl abbreviator.pl 47475782130 2
Salida:
47.48G