17
\$\begingroup\$

Challenge and origin

On Stack Overflow a popular question is: How to convert byte size into human readable format in java? The most up voted answer has a quite nice method for doing this, but this is codegolf and we can do better, can't we?

Your challenge is to write a method or program that coverts the given number of bytes to the correct human readable format and prints the result to the standard out of your language.*

*See the rules for more clarification!

Input

The input will always be a positive number of bytes with a maximum of (2^31)-1.

Output

You may choose if you prefer the International System of Units or the binary notation as output (the SI notation probably saves you some bytes).

SI:      B, kB,  MB,  GB  
Binary:  B, KiB, MiB, GiB

Note: Higher units than GB or GiB are not posible due to the restricted input range.

Example output

International System of Units:

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

Binary:

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

Rules

  • Build-in functions for byte formatting are not allowed!
  • The output should always be in the same notation standard, you may not mix SI or binary;
  • The output should always be in the largest unit possible where the resulting number is still higher or equal to one;
  • The output should always have one decimal number, but you may choose to print an integer number when the resulting output is in bytes (B);
  • You may choose if you would like to add a space, tab or nothing between the number and the unit;
  • Input is received via STDIN or function parameters;
  • Output is printed to the console or returned as string (or similar character container);
  • This is code golf, so the shortest answer wins. Have fun!

Edit: Even more clarification

Some numbers have interesting rounding behaviors like the number 999950. Most code implementations would return 1000.0 kB instead of 1.0 MB. Why? Because 999950/1000 evaluates to 999.950 which is effectively rounded to 1000.0 when using String.format in Java (in most other languages too). Hench some extra checks are needed to handle cases like this.

For this challenge both styles, 1000.0 kB and 1.0 MB are accepted, although the last style is preferred.

Pseudo code / java test code:


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));
}

\$\endgroup\$
11
  • 1
    \$\begingroup\$ Technically, SI kilobytes should use kB (note the lowercase k) \$\endgroup\$ Commented Jun 20, 2015 at 11:21
  • \$\begingroup\$ Good point, fixed! \$\endgroup\$
    – Rolf ツ
    Commented Jun 20, 2015 at 11:21
  • 1
    \$\begingroup\$ I don't want to limit to much, so I would say the spacing may be inconsistent. But with this rule: The difference in space and tab characters for different valid inputs may not exceed 10. (To keep it all a bit "human readable") \$\endgroup\$
    – Rolf ツ
    Commented Jun 20, 2015 at 14:05
  • 2
    \$\begingroup\$ What's the expected output for 999999 and 1000000? 160581 exhibits rounding, so should it be 1000.0kB and 1.0MB? \$\endgroup\$
    – Sp3000
    Commented Jun 20, 2015 at 15:41
  • 3
    \$\begingroup\$ @Sp3000 That's a good question, the nicest solution would be for 999999 to display 1.0 MB. But for this challenge I would say 1000.0 KB and similar rounding cases are fine too. \$\endgroup\$
    – Rolf ツ
    Commented Jun 20, 2015 at 17:32

22 Answers 22

10
\$\begingroup\$

TI-BASIC, 44

Would be the right tool for the job if TI-BASIC had halfway decent string manipulation (I had to resort to overwriting the exponent of the number, displayed in engineering notation, with the unit). As it is it rounds and outputs correctly, but it's not even close to winning entries. Maybe a different calculator language could win this one?

Fix 1
Eng
ClrHome
Disp Ans
Output(1,15,sub(" kMG",1+iPart(log(Ans+.5)/3),1)+"B

Input in the form [number]:[program name] on the homescreen.

Given test cases:

Input       Output (leading spaces intentional; screen clear before each output)
0                      0.0 B
999                  999.0 B
1000                   1.0kB
1023                   1.0kB
1024                   1.0kB
1601                   1.6kB
160581               160.6kB
4066888                4.1MB
634000000            634.0MB
2147483647             2.1GB
\$\endgroup\$
2
  • \$\begingroup\$ I had absolutely no idea that TI-BASIC was so versatile haha \$\endgroup\$
    – Beta Decay
    Commented Jun 20, 2015 at 20:12
  • 1
    \$\begingroup\$ TI-BASIC isn't versatile, but there are often strange workarounds for a few of its shortcomings. \$\endgroup\$
    – lirtosiast
    Commented Jun 21, 2015 at 5:59
6
\$\begingroup\$

CJam, 35 27 bytes

ri{_e-3_i}g;1mOo]," kMG"='B

Thanks Dennis for removing 8 bytes.

This doesn't print .0 in the online interpreter. But as Dennis has pointed out, it works fine in the Java interpreter.

Explanation

ri         e# Read the input as an integer.
{          e# Do:
    _e-3   e#   Make a copy and divide by 1000.
           e#   This will generate one more item in the stack for each iteration.
    _i     e#   Make a copy and truncate to integer.
}g         e# until the integer part is 0.
;          e# Discard the final value with integer part 0.
1mOo       e# Output the number before it with the correct format.
],         e# Count the number of iterations - 1.
" kMG"=    e# Select a character according to the number of iterations.
'B         e# Output B.
\$\endgroup\$
6
  • \$\begingroup\$ ri{_e-3XmO_i}g;o]," kMG"='B (27 bytes) \$\endgroup\$
    – Dennis
    Commented Jun 20, 2015 at 16:56
  • \$\begingroup\$ @Dennis Thanks for the 1mO. But this code doesn't work for 1149999... \$\endgroup\$
    – jimmy23013
    Commented Jun 20, 2015 at 17:16
  • \$\begingroup\$ ri{_e-3_i}g;1mOo]," kMG"='B should. \$\endgroup\$
    – Dennis
    Commented Jun 20, 2015 at 17:18
  • \$\begingroup\$ Scratch that, that has other bugs. \$\endgroup\$
    – Dennis
    Commented Jun 20, 2015 at 17:19
  • \$\begingroup\$ 999999 becomes 1000kB. Reading the question again, I'm not sure if 1000kB would actually be wrong. \$\endgroup\$
    – Dennis
    Commented Jun 20, 2015 at 17:28
5
\$\begingroup\$

Pyth, 29 27 bytes

p@" kMG"Js.lQK^T3.RcQ^KJ1\B

Demonstration. Test Harness.

Explanation:

p@" kMG"Js.lQK^T3.RcQ^KJ1\B
                                 Implicit: Q = eval(input())
p                                print, in the order 2nd arg then 1st arg:
             K^T3                K = 10^3 = 1000
          .lQK                   log of Q base K
         s                       Floored
        J                        Store to J
 @" kMG"J                        The Jth character of ' kMG'
                     ^KJ         K^J
                   cQ            Q/K^J (Floating point division)
                 .R     1        Round to 1 decimal place.
                         \B      Print a trailing 'B'.
\$\endgroup\$
2
\$\begingroup\$

CJam, 28

r_dA@,(3/:X3*#/1mO" kMG"X='B

Try it online

Note: it doesn't show ".0" with the online interpreter, but does so with the official java interpreter.

Explanation:

r_          read and duplicate
dA          convert to double and push 10
@           bring the initial string to the top
,(          get the length and decrement
3/          divide by 3 (for thousands)
:X3*        store in X and multiply by 3 again
#           raise 10 to that power
/           divide the original number by it
1mO         round to 1 decimal
" kMG"X=    convert X from 0/1/2/3 to space/k/M/G
'B          add a 'B'
\$\endgroup\$
3
  • \$\begingroup\$ What is the backtick for? \$\endgroup\$
    – Dennis
    Commented Jun 20, 2015 at 16:50
  • \$\begingroup\$ @Dennis showing .0 in the online interpreter \$\endgroup\$ Commented Jun 20, 2015 at 16:51
  • \$\begingroup\$ It works fine in the Java interpreter without the backtick, so I don't think you need it. \$\endgroup\$
    – Dennis
    Commented Jun 20, 2015 at 16:52
2
\$\begingroup\$

Python 2 - 76 bytes

Uses the Internation System of Units, simply because it's easier to do in your head ;)

n=input();m=0;f=1e3
while n>=f:n/=f;m+=2
print"%.1f%s"%(n,'B kBMBGB'[m:m+2])
\$\endgroup\$
5
  • \$\begingroup\$ it seems not ok for me, it doesn't respect the asked formatting, for exemple if I submit "2147483647" I obtain "2.000000GB" - The question asks for one decimal, and maybe a space. \$\endgroup\$
    – dieter
    Commented Jun 20, 2015 at 12:47
  • 1
    \$\begingroup\$ Also, this is 79 bytes according to this. This is 75 bytes. I don't believe it was specified that there needs to be a space between the number and the unit. \$\endgroup\$
    – Kade
    Commented Jun 20, 2015 at 16:30
  • \$\begingroup\$ you can save one byte with f=1e3 \$\endgroup\$
    – mbomb007
    Commented Jun 22, 2015 at 21:40
  • \$\begingroup\$ @mbomb007 Actually it saved 2 bytes because 1e3 is a float \$\endgroup\$
    – Beta Decay
    Commented Jun 23, 2015 at 5:58
  • \$\begingroup\$ I knew it was a float. I guess I just can't count... \$\endgroup\$
    – mbomb007
    Commented Jun 23, 2015 at 14:46
2
\$\begingroup\$

Haskell, 119

I sadly couln't find a shorter way in Haskell to ensure 1 decimal place in floats, but I'm posting for posterity.

import Text.Printf
a#n|p>=1=(a+1)#p|1<2=(a,n)where p=n/1000
m n=let(a,b)=0#n in printf"%.1f"b++["B","kB","MB","GB"]!!a

Usage:

> m 160581
"160.6kB"

Moderately less golfed version:

import Text.Printf

countThousands :: Int -> Float -> (Int, Float)
countThousands count num
 |nextNum >= 1 = countThousands (count+1) nextNum
 |otherwise    = (count,num)
 where nextNum = num/1000

printHuman :: Float -> String
printHuman n = let (a,b) = countThousands 0 n in 
  (printf "%.1f" b) ++ (["B","kB","MB","GB"]!!a)
\$\endgroup\$
2
\$\begingroup\$

Ruby, 84

def f(n)
n2=Math.log10(n).to_i/3
return '%.3f'% (n/1e3**n2)+['','k','M','G'][n2]
end
p f(9012345678.0)=='9.012G'

Python, 94

import math
def f(n):
 n2=int(math.log10(n)/3)
 return '%.3f'%(n/1e3**n2)+('','k','M','G')[n2]
print(f(9012345678)=='9.012G')

JavaScript, 104

function f(n){
let n2=Math.trunc(Math.log10(n)/3);
return (n/1e3**n2).toFixed(3)+['','k','M','G'][n2];
}
console.log(f(9012345678)=='9.012G');

PHP, 105

<?php
function f($n){
$n2=(int)(log10($n)/3);
return sprintf('%.3f',$n/1e3**$n2).['','k','M','G'][$n2];
}
var_dump(f(9012345678)=='9.012G');

Dart, 146

import 'dart:math';
String f(double n){
var n2=(log(n)/ln10/3).toInt();
var n3=n/pow(1e3,n2);
return n3.toStringAsFixed(3)+['','k','M','G'][n2];
}
void main(){
print(f(9012345678)=='9.012G');
}
\$\endgroup\$
3
  • \$\begingroup\$ It's generally recommended to post different languages as separate answers. \$\endgroup\$
    – Razetime
    Commented Nov 18, 2020 at 4:06
  • \$\begingroup\$ @Razetime ok I split it in half - but 10 answers seems like a lot \$\endgroup\$
    – Zombo
    Commented Nov 18, 2020 at 4:38
  • \$\begingroup\$ Cool! Do keep in mind next time. \$\endgroup\$
    – Razetime
    Commented Nov 18, 2020 at 4:54
1
\$\begingroup\$

POWERSHELL,190

$x=Read-Host
function f($a,$b){"$x`t"+[math]::Round($x/$a,1).ToString("F1")+"`t$b"}
if(1KB-gt$x){f 1 "B"}elseif(1MB-gt$x){f 1KB KiB}
elseif(1GB-gt$x){f 1MB MiB}elseif(1TB-gt$x){f 1GB GiB}

usage

PS C:\> .\makehum.ps1
1601
1601    1.6     KiB
PS C:\> .\makehum.ps1
4066888
4066888 3.9     MiB
PS C:\> .\makehum.ps1
160581
160581  156.8   KiB
PS C:\> .\makehum.ps1
634000000
634000000       604.6   MiB
PS C:\> .\makehum.ps1
2147483647
2147483647      2.0     GiB
PS C:\>
\$\endgroup\$
1
\$\begingroup\$

Java, 106 bytes

This one's a method that takes a number and returns a string.

String f(int n){int k=0;for(;n>1e3;k++)n/=1e3;return(int)(10*n)/10.0+new String[]{"","k","M","G"}[k]+"B";}
\$\endgroup\$
3
  • \$\begingroup\$ You are allowed to program a function returning a string instead of a complete program, it may save you some bytes ;) \$\endgroup\$
    – Rolf ツ
    Commented Jun 20, 2015 at 11:41
  • \$\begingroup\$ Three things: If you're converting a to a double anyway (I don't know if it's necessary), you can use 1e3 for 1000; you can convert that while() to a for() and use the free semicolons; and I don't know if this works because it seems to display all the decimal digits, not just one past the decimal place. \$\endgroup\$
    – lirtosiast
    Commented Jun 20, 2015 at 12:46
  • \$\begingroup\$ @ThomasKwa: Last I checked, the question didn't seem to explicitly specify that. But I guess it does now. \$\endgroup\$ Commented Jun 20, 2015 at 20:15
1
\$\begingroup\$

C, 77 75

f(float l){char*u=" kMG";while((l/=1e3)>=1)++u;printf("%.1f%cB",l*1e3,*u);}

This uses SI units and takes the 1000.0kB option for rounding.

Expanded code:

f(float l)
{
    char *u = " kMG";
    while ((l/=1000) >= 1)
        ++u;
    printf("%.1f%cB", l*1000, *u);
}

Output

9 => 9.0 B
9999 => 10.0kB
1023 => 1.0kB
1024 => 1.0kB
999990 => 1000.0kB
1048575 => 1.0MB
1048576 => 1.0MB
2147483647 => 2.1GB

Variants

To get binary units, change 1000 to 1024, and add i to the format string if there's a multiplier. To avoid 4-digit rounding, compare >=.95 instead of >=1. To accept larger units, extend the u string. Combining all these options, we get:

f(float l)
{
    char*u=" kMGTPEZY";
    while((l/=1024)>=.95)++u;
    printf(*u-' '?"%.1f%ciB":"%.0fB",l*1024,*u);
}

Variant output

9 => 9B
9999 => 9.8kiB
1023 => 1.0kiB
1024 => 1.0kiB
999990 => 1.0MiB
1048575 => 1.0MiB
1048576 => 1.0MiB
2147483647 => 2.0GiB
1000000000 => 953.7MiB
1000000000000 => 931.3GiB
1000000000000000 => 909.5TiB
1000000000000000000 => 888.2PiB
1000000000000000000000 => 867.4EiB
1000000000000000000000000 => 847.0ZiB
999999999999999999999999999 => 827.2YiB
1176043059457204080886151645 => 972.8YiB

Test program

Pass any number of inputs as command-line arguments:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    while (*++argv) {
        printf("%s => ", *argv);
        f(strtod(*argv, 0));
        puts("");
    }
    return 0;
}
\$\endgroup\$
1
  • \$\begingroup\$ Nice one ;) Well executed! \$\endgroup\$
    – Rolf ツ
    Commented Jun 25, 2015 at 15:46
1
\$\begingroup\$

Rust, 124

fn f(n:f64)->String{
let n2=n.log(1e3);
let n3=n/1e3f64.powi(n2 as i32);
format!("{:.3}",n3)+["","k","M","G"][n2 as usize]
}
fn main(){
println!("{}",f(9012345678e0)=="9.012G");
}

Nim, 139

import math,strformat
proc f(n:float):string=
 let n2=int log10(n)/3
 let n3=n/pow(1e3,float n2)
 return fmt"{n3:.3f}"&["","k","M","G"][n2]
echo f(9012345678e0)=="9.012G"

Go, 145

package m
import(."fmt"
."math")
func f(g float64)string{h:=int(Log10(g))/3
i:=g/Pow10(h*3)
return Sprintf("%.3f",i)+[]string{"","k","M","G"}[h]}

D, 156

import std.format,std.math,std.stdio;
string f(real n){
auto n2=cast(int)log10(n)/3;
auto n3=n/pow(1e3,n2);
return format("%.3f",n3)~["","k","M","G"][n2];
}
void main(){
writeln(f(9012345678)=="9.012G");
}

C#, 168

using System;
class P{
static string f(double n){
var n2=(int)Math.Log10(n)/3;
var n3=n/Math.Pow(1e3,n2);
return String.Format("{0:f3}",n3)+new[]{"","k","M","G"}[n2];
}
static void Main(){
Console.WriteLine(f(9012345678)=="9.012G");
}
}
\$\endgroup\$
0
\$\begingroup\$

Python 2, 127 bytes

Using the ISU. The snippet declares a function 'C' that takes the number to be converted as argument.

C=lambda v:min(['%.1f %sB'%(x,u)for x,u in[(v/1000.0**i,'bkMG'[i])for i in range(4)]if x>=1]).replace('.0 b',' ')if v else'0 B'

Some test code:

    print 'Input\tOutput'
for v in [0,999,1000,1023,1023,1601,160581,4066888,634000000,2147483647]:
 print v,C(v)
\$\endgroup\$
1
  • \$\begingroup\$ You can use 1e3 instead of 1000.0 \$\endgroup\$
    – mbomb007
    Commented Jun 22, 2015 at 21:42
0
\$\begingroup\$

JavaScript (ES6), 71

Using SI units - A function returning the requested string.

f=(a,b=3)=>+(r=eval('a/1e'+b*3).toFixed(1))[0]?r+' kMG'[b]+'B':f(a,b-1)

This shorter one follows the rules, particularly 3 and 4

  • The output should always be in the largest unit possible where the resulting number is still higher or equal to one then 995 => 1.0kB
  • The output should always have one decimal number, but you may choose to print an integer number when the resulting output is in bytes (B) I choose not, so 10 => 10.0 B

Alas, this way, the results do not match the examples.

To match the examples, here is a longer one, special cased for small numbers (82 bytes)

f=(a,b=3)=>a<1e3?a+'B':+(r=eval('a/1e'+b--*3).toFixed(1))[0]?r+'kMG'[b]+'B':f(a,b)

Run the snippet to test (being EcmaScript 6, Firefox only)

f=(a,b=3)=>+(r=eval('a/1e'+b*3).toFixed(1))[0]?r+' kMG'[b]+'B':f(a,b-1)
Value <input id=I><button onclick="O.innerHTML+=f(+I.value)+'\n'">-></button><pre id=O></pre>

\$\endgroup\$
0
\$\begingroup\$

Ruby, 91 bytes

n=gets.to_i;i=0;while n>1023;n/=1024.0;i+=1;end;puts "#{n.round 1} #{%w[B KiB MiB GiB][i]}"

I could probably do a bit better if I tried harder but here's what I've got so far.

\$\endgroup\$
1
  • \$\begingroup\$ Use 1024. instead of 1024.0. \$\endgroup\$
    – mbomb007
    Commented Jun 22, 2015 at 21:45
0
\$\begingroup\$

Python, 61 bytes

f=lambda n,i=0:"%.1f%cB"%(n," kMG"[i])*(n<1e3)or f(n/1e3,i+1)

Call like f(999). Note that 1e3 is a float, so this works with both Python 2 and Python 3.

\$\endgroup\$
0
\$\begingroup\$

PHP4.1, 63 62 bytes

Not the best golfing, but surely is quite short.

<?for($S=kMG;$B>1e3;$I++)$B/=1e3;printf("%.1f{$S[$I-1]}B",$B);

To use it, access over POST/GET or set a value in the SESSION, on the key B.

Leave the key I unset!

\$\endgroup\$
1
  • \$\begingroup\$ @downvoter: care to explain why you downvoted this, 5 years later? Almost 5 and a half ... \$\endgroup\$ Commented Nov 18, 2020 at 19:15
0
\$\begingroup\$

SpecBAS - 100 bytes

Using the ISU convention.

I realised that having a variable set to 1e3 (which needs a LET statement to assign it), and then using that variable in the working out, actually used more characters than just hardcoding the 1e3 where it was needed.

1 INPUT n: LET i=1
2 DO WHILE n>1e3: LET n=n/1e3: INC i: LOOP 
3 PRINT USING$("&.*0#",n);" kMG"(i);"B"
\$\endgroup\$
0
\$\begingroup\$

Javascript ES5, 69 bytes

This uses a different way to reach the end goal that @edc65's answer.
Actually, this is pretty close to my PHP answer.

for(i=+prompt(z=0);i>1e3;z++)i/=1e3;alert(i.toFixed(1)+' kMG'[z]+'B')

Simply run the stack snippet or paste this on your console.

\$\endgroup\$
0
\$\begingroup\$

Ruby, 128 bytes

c=->i{p i.to_s+'B'if i<1e3;p (i/1e3).to_s+'kB'if i>=1e3&&i<1e6;p (i/1e6).to_s+'MB'if i>=1e6&&i<1e9;p (i/1e9).to_s+'GB'if i>=1e9}

I did it the long way, this is pretty bad.

Output

c[0] # => "0B"
c[999] # => "999B"
c[1000] # => "1.0kB" 
c[1023] # => "1.023kB"
c[1024] # => "1.024kB"
c[1601] # => "1.601kB"
c[160581] # => "160.581kB"
c[4066888] # => "4.066888MB"
c[634000000] # => "634.0MB"
c[2147483647] # => "2.147483647GB"

Edit

Added TB for an extra 39 bytes

c=->i{p i.to_s+'B'if i<1e3;p (i/1e3).to_s+'kB'if i>=1e3&&i<1e6;p (i/1e6).to_s+'MB'if i>=1e6&&i<1e9;p (i/1e9).to_s+'GB'if i>=1e9&&i<1e12;p (i/1e12).to_s+'TB'if i>=1e12}

Output:

c[1000000000000] # => "1.0TB"
\$\endgroup\$
0
\$\begingroup\$

Ruby, 90 bytes

proc{|n|q=((1..3).find{|i|n<(1<<i*10)}||4)-1;[n*10/(1<<q*10)/10.0,%w[B kB MB GB][q]].join}
\$\endgroup\$
0
\$\begingroup\$

Sed -r, 218+1

I'm using SI units; I think that choosing binary units would be a courageous policy. ;-)

s/(.)((...)+)$/\1z\2/;h;s/[^z]*z?//;s/.../k/g;s/kk/M/;s/Mk/G/;x;s/(z.)[5-9].*/\1c/;s/(z.c?).*/\1/;:;s/9c/c0/;s/zc/cz/;t;s/(^|0)c/1/;s/1c/2/;s/2c/3/;s/3c/4/;s/4c/5/;s/5c/6/;s/6c/7/;s/7c/8/;s/8c/9/;G;s/\n//;s/$/B/;y/z/./

Reformatted:

#!/bin/sed -rf

# Place decimal point (use z as shorthand for \.)
s/(.)((...)+)$/\1z\2/
h

# count thousands into hold space
s/[^z]*z?//
s/.../k/g
s/kk/M/;s/Mk/G/
x

# truncate to 1 decimal place
s/(z.)[5-9].*/\1c/
s/(z.c?).*/\1/

# propagate carry
:
s/9c/c0/
s/zc/cz/
t
s/(^|0)c/1/
s/1c/2/
s/2c/3/
s/3c/4/
s/4c/5/
s/5c/6/
s/6c/7/
s/7c/8/
s/8c/9/

# Append units
G;s/\n//
s/$/B/
y/z/./

Output

1 => 1B
9 => 9B
99 => 99B
999 => 999B
1000 => 1.0kB
9999 => 10.0kB
99949 => 99.9kB
99950 => 100.0kB
99999 => 100.0kB
999999 => 1000.0kB
9999999 => 10.0MB
9999999999 => 10.0GB
1000 => 1.0kB
10000 => 10.0kB
10005 => 10.0kB
10440 => 10.4kB
10450 => 10.5kB
10950 => 11.0kB

Variations

The rules seem to imply round-to-nearest, but for human display, I believe rounding down is an acceptable alternative, and saves 123 bytes (better than 50%):

s/(.)((...)+)$/\1.\2/;h;s/[^\.]*\.?//;s/.../k/g;s/kk/M/;s/Mk/G/;x;s/(\..).*/\1/;G;s/\n//;s/$/B/

The natural extension to larger units (still rounding down, 130+1 bytes):

s/(.)((...)+)$/\1.\2/;h;s/[^\.]*\.?//;s/.../k/g;s/kk/M/g;s/Mk/G/;s/MM/T/g;s/TT/Y/;s/TM/E/;s/TG/Z/;x;s/(\..).*/\1/;G;s/\n//;s/$/B/

Variation output:

1 => 1B
9 => 9B
99 => 99B
999 => 999B
1000 => 1.0kB
9999 => 9.9kB
99949 => 99.9kB
99950 => 99.9kB
99999 => 99.9kB
999999 => 999.9kB
9999999 => 9.9MB
9999999999 => 9.9GB
1000 => 1.0kB
10000 => 10.0kB
10005 => 10.0kB
10440 => 10.4kB
10450 => 10.4kB
10950 => 10.9kB
1000000000 => 1.0GB
1000000000000 => 1.0TB
1000000000000000 => 1.0MGB
1000000000000000000 => 1.0EB
1000000000000000000000 => 1.0ZB
1000000000000000000000000 => 1.0YB
999999999999999999999999999 => 999.9YB
\$\endgroup\$
1
  • \$\begingroup\$ Great job! I like that you thought about all the different options! \$\endgroup\$
    – Rolf ツ
    Commented Jun 25, 2015 at 9:31
0
\$\begingroup\$

brainfuck, 396 376 bytes

,[<[->>+<<]>>+>,]<<[>[<<+>>-]<<<]<-------<---<--<-[>+>-->+>>>>>>+<<<<<<<<<-------]>>>>>>>+++>>++++<<<<<--[>>>+<<<++++++]+>-[-[-[-[-[-[-[-[-[-[-<->]<[>>.>.>.[<<]>.>>>-]>]<[->>.>>.>>.<<<.>>>>>.<<<.<<<<<]>]<[->>.>>.<.>>>.<.<<<<<]>]<[->>.>.>.>.[<]<]>]<[>>.>>.>>.<<<.>>>>>.[<<]>>.>>-]>]<[>>.>>.<.>>>.[<<]>>.>>-]>]<[->>.>.>.<<<<<<.>>]>]<[->>[.>>]<<[<<]]>]<[->>.>>.<<<<]>]<[->>.<<]<.

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.