Desafio e origem
No Stack Overflow, uma pergunta popular é: Como converter o tamanho de bytes em formato legível por humanos em java? A resposta mais votada tem um método bastante legal para fazer isso, mas esse é um codegolf e podemos fazer melhor, não podemos?
Seu desafio é escrever um método ou programa que cubra o número especificado de bytes no formato legível humano correto e imprima o resultado no padrão do seu idioma. *
* Veja as regras para mais esclarecimentos!
Entrada
A entrada sempre será um número positivo de bytes com um máximo de (2 ^ 31) -1.
Resultado
Você pode escolher se prefere o Sistema Internacional de Unidades ou a notação binária como saída (a notação SI provavelmente economiza alguns bytes).
SI: B, kB, MB, GB
Binary: B, KiB, MiB, GiB
Nota: Unidades superiores a GB ou GiB não são possíveis devido ao intervalo de entrada restrito.
Saída de exemplo
Sistema Internacional de Unidades:
Input Output
0 0.0 B
999 999.0 B
1000 1.0 kB
1023 1.0 kB
1024 1.0 kB
1601 1.6 kB
160581 160.6 kB
4066888 4.1 MB
634000000 634.0 MB
2147483647 2.1 GB
Binário:
Input Output
0 0.0 B
999 999.0 B
1000 1000.0 B
1023 1023.0 B
1024 1.0 KiB
1601 1.6 KiB
160581 156.8 KiB
4066888 3.9 MiB
634000000 604.6 MiB
2147483647 2.0 GiB
Regras
- Funções internas para formatação de bytes não são permitidas!
- A saída deve sempre estar no mesmo padrão de notação; você não pode misturar SI ou binário;
- A saída deve sempre estar na maior unidade possível, onde o número resultante ainda é maior ou igual a um;
- A saída sempre deve ter um número decimal, mas você pode optar por imprimir um número inteiro quando a saída resultante estiver em bytes (B);
- Você pode escolher se deseja adicionar um espaço, tabulação ou nada entre o número e a unidade;
- A entrada é recebida via STDIN ou parâmetros de função;
- A saída é impressa no console ou retornada como string (ou contêiner de caractere semelhante);
- Isso é código de golfe, então a resposta mais curta vence. Diverta-se!
Edit: Esclarecimentos ainda mais
Alguns números têm comportamentos interessantes de arredondamento, como o número 999950. A maioria das implementações de código retornaria 1000,0 kB em vez de 1,0 MB. Por quê? Porque 999950/1000 é avaliado para 999.950, que é efetivamente arredondado para 1000.0 ao usar String.format em Java (na maioria das outras linguagens também). Hench algumas verificações extras são necessárias para lidar com casos como este.
Para esse desafio, os dois estilos são aceitos 1000,0 kB e 1,0 MB, embora o último estilo seja o preferido.
Pseudo-código / código de teste java:
public static String bytesToSI(long bytes){ if (bytes < 1000){ return bytes + ".0 B"; } //Without this rounding check: //999950 would be 1000.0 kB instead of 1.0 MB //999950000 would be 1000.0 MB instead of 1.0 GB int p = (int) Math.ceil(Math.log(bytes) / Math.log(1000)); if(bytes/Math.pow(1000, p) < 0.99995){ p--; } //Format return String.format("%.1f %sB", bytes/Math.pow(1000, p), "kMGTPE".charAt(p-1)); }
999999e 1000000? 160581exibe arredondamento, então deveria ser 1000.0kBe 1.0MB?
kB(note a minúscula k)