问题
I have data in bytes. I need to draw this values as human readable labels on a chart (like 2.5KB, 14MB etc.) and need to help with function (input data - actual value, output - human readable string).
I did funcion like this, but I want more elegant realization
function tickFormatter(value, type) {
var suffix = (type == "bytes") ? ['B', 'KB', 'MB', 'GB'] : ['', 'K', 'M', 'G']
if(value > (1024 * 1024 * 1024 * 1024)) {
return (value / (1024 * 1024 * 1024 * 1024)).toFixed(2) + suffix[3]
} else if(value > (1024 * 1024 * 1024)) {
return (value / (1024 * 1024 * 1024)).toFixed(2) + suffix[2]
} else if (value > (1024 * 1024)) {
return (value / (1024 * 1024)).toFixed(2) + suffix[1]
} else {
return value.toFixed(2) + suffix[0]
}
}
回答1:
I love this implementation: clear and compact:
function readablizeBytes(bytes) {
var s = ['bytes', 'kB', 'MB', 'GB', 'TB', 'PB'];
var e = Math.floor(Math.log(bytes) / Math.log(1024));
return (bytes / Math.pow(1024, e)).toFixed(2) + " " + s[e];
}
Usage:
readablizeBytes(10000000)
"9.54 MB"
I don't take the credit of this.
回答2:
This is what I use. It rounds up to the nearest unit, so 1000 is "0.98KB" If you don't want that, then change the first Math.round to a floor.
var SizePrefixes = ' KMGTPEZYXWVU';
function GetHumanSize(size) {
if(size <= 0) return '0';
var t2 = Math.min(Math.round(Math.log(size)/Math.log(1024)), 12);
return (Math.round(size * 100 / Math.pow(1024, t2)) / 100) +
SizePrefixes.charAt(t2).replace(' ', '') + 'B';
}
回答3:
Perhaps something like this?
function readable (nb_bytes) {
if (nb_bytes < 1024) return nb_bytes + 'B';
else if (nb_bytes < 1024 * 1024) return (Math.round((nb_bytes / 1024) * 100) / 100) + 'KB';
else return (Math.round((nb_bytes / 1024 / 1024) * 100) / 100) + 'MB';
}
[EDIT]
Alright, since you want something more elegant, I assume you're thinking of a loop. Maybe this will suit your needs:
function readable (nb_bytes,type) {
var suffix = type ? ['B','KB','MB','GB'] : ['','K','M','G'];
var i = 0;
while (nb_bytes > 1024 && i < suffix.length - 1) {
++i;
nb_bytes = Math.round((nb_bytes / 1024) * 100) / 100;
}
return (nb_bytes) + suffix[i];
}
Here I assumed type
was a boolean - change to whatever suits you best.
回答4:
Modified version of Amer's:
(function GetHumanSize(size) {
var SizePrefixes = ['','K','M','G','T','P','E','Z','Y'];
if(size <= 0) return '0';
var t2 = Math.min(Math.round(Math.log(size)/Math.log(1024)),
SizePrefixes.length-1);
return String((Math.round(size * 100 / Math.pow(1024, t2)) / 100)) +
' ' + SizePrefixes[t2] + 'iB';
})(Math.pow(2,131)) === "2251799813685248 YiB"
With:
- IEC suffixes
- No non-standard suffixes
回答5:
function formatSize(size, standard) {
if (standard) {
standard = standard.toLowerCase();
}
var n = 0,
base = standard == 'si' ? 1000 : 1024,
prefixes = ' KMGTPEZY';
if (size < 1) {
return 0;
}
else if (size >= base) {
n = Math.floor( Math.log(size) / Math.log(base) );
if (n >= prefixes.length) {
return 'N/A';
}
size = ( size / Math.pow(base, n) ).toFixed(2) * 1 + ' ';
}
return size + prefixes[n] + ( n && standard == 'iec' ? 'i' : '' ) + 'B';
}
Test:
for (var i = 0; i++ < 10;) console.log( formatSize( Math.pow(10, i) ) );
Output:
10 B
100 B
1000 B
9.77 KB
97.66 KB
976.56 KB
9.54 MB
95.37 MB
953.67 MB
9.31 GB
回答6:
I took what I felt the best of the top two solutions and came up with this, its faster than the first, slower than the second. But its purpose is to always have exactly 3 characters, and not round. The reason for the 3 character limit was due to size constraints for the container it was being placed into. Additionally should you want to use it to format non base 2 numbers all you need to do is change kilo to 1000. It also short circuits if the number is under 1k
var kilo = 1024, suffix = ' KMGTPEZYXWVU', humanReadable = function (number) {
var retValue = false;
if (typeof number == "number") {
if (number < kilo) {
retValue = number.toString();
} else {
var e = Math.floor(Math.log(number) / Math.log(kilo));
retValue = Number((number / Math.pow(kilo, e)).toString().slice(0, 3)) + suffix.charAt(e) + 'B';
}
}
return retValue;
};
回答7:
You answers really helped me, so I decided to write an utility method that solves this problem of size formatting once and for all.
Check out my JSUtils repo wiki page: https://bitbucket.org/AAverin/jsutils/ | https://github.com/AAverin/JSUtils It has humanReadeableSize method that uses Amir's way of rounding the size, but also supports conversion between the usual base of 2 (KiB, MiB) and base 10 numbers (KB, MB).
It can round down to the closest value, but also round up in case you want, for example, get how much KB are in PB.
Feel free to grab it and use in your projects!
回答8:
Could use number_to_human_size(number, options = {})
number_to_human_size(1234567)
examples:
number_to_human_size(123) # => 123 Bytes
number_to_human_size(1234) # => 1.21 KB
number_to_human_size(12345) # => 12.1 KB
number_to_human_size(1234567) # => 1.18 MB
number_to_human_size(1234567890) # => 1.15 GB
number_to_human_size(1234567890123) # => 1.12 TB
number_to_human_size(1234567, precision: 2) # => 1.2 MB
number_to_human_size(483989, precision: 2) # => 470 KB
number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB
as in documentation http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_to_human_size
来源:https://stackoverflow.com/questions/4498866/actual-numbers-to-the-human-readable-values