实际数字到人类可读值

发布于 2024-10-08 14:54:44 字数 682 浏览 9 评论 0原文

我有以字节为单位的数据。我需要在图表上绘制这些值作为人类可读的标签(如 2.5KB、14MB 等),并且需要帮助实现功能(输入数据 - 实际值,输出 - 人类可读字符串)。

我确实是这样的,但我想要更优雅的实现

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]
    }
}

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]
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

饮惑 2024-10-15 14:54:44

我喜欢这个实现:清晰紧凑:

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

用法:

readablizeBytes(10000000)
"9.54 MB"

我不相信这一点。

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.

年少掌心 2024-10-15 14:54:44

这就是我用的。它向上舍入到最接近的单位,因此 1000 是“0.98KB”
如果您不希望这样,请将第一轮 Math.round 更改为下限。

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

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';
}
始终不够爱げ你 2024-10-15 14:54:44

也许是这样的?

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

[编辑]

好吧,既然你想要更优雅的东西,我假设你正在考虑一个循环。也许这会满足您的需求:

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

这里我假设 type 是一个布尔值 - 更改为最适合您的值。

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.

烟织青萝梦 2024-10-15 14:54:44

Amer 的修改版本:

(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"

带:

  • IEC 后缀
  • 无非标准后缀

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
桜花祭 2024-10-15 14:54:44

我采用了我认为最好的两个解决方案,并提出了这个,它比第一个更快,比第二个慢。但其目的是始终只有 3 个字符,而不是圆形。 3 个字符限制的原因是由于其所放入的容器的大小限制。另外,如果你想用它来格式化非基数 2 的数字,你需要做的就是将 kilo 更改为 1000。如果数字低于 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;
};

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;
};
原来分手还会想你 2024-10-15 14:54:44
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';
}

测试:

for (var i = 0; i++ < 10;) console.log( formatSize( Math.pow(10, i) ) ); 

输出:

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

Hello from 2022:

function humanSize(size, iec = true) {
  let base = iec ? 1024 : 1000
  let units = ['', 'K', 'M', 'G', 'T']
  let i = Math.log(size) / Math.log(base) | 0
  return `${(size / Math.pow(base, i)).toFixed(2) * 1} ${units[i]}${i && iec ? 'i' : ''}B`
}
undefined
humanSize(2048)
'2 KiB'
humanSize(2000)
'1.95 KiB'
humanSize(500000000000)
'465.66 GiB'
humanSize(500000000000, false)
'500 GB'
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

Hello from 2022:

function humanSize(size, iec = true) {
  let base = iec ? 1024 : 1000
  let units = ['', 'K', 'M', 'G', 'T']
  let i = Math.log(size) / Math.log(base) | 0
  return `${(size / Math.pow(base, i)).toFixed(2) * 1} ${units[i]}${i && iec ? 'i' : ''}B`
}
undefined
humanSize(2048)
'2 KiB'
humanSize(2000)
'1.95 KiB'
humanSize(500000000000)
'465.66 GiB'
humanSize(500000000000, false)
'500 GB'
煮茶煮酒煮时光 2024-10-15 14:54:44

您的回答确实对我很有帮助,所以我决定编写一个实用方法来一劳永逸地解决大小格式的问题。

查看我的 JSUtils 存储库 wiki 页面:https://bitbucket.org/AAverin/jsutils/ | https://github.com/AAverin/JSUtils
它有 humanReadeableSize 方法,使用 Amir 的方式舍入大小,但也支持通常的基数 2(KiB、MiB)和基数 10 数字(KB、MB)之间的转换。

它可以向下舍入到最接近的值,但如果您需要,也可以向上舍入,例如,获取 PB 中有多少 KB。

请随意抓住它并在您的项目中使用!

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!

江湖彼岸 2024-10-15 14:54:44

可以使用 number_to_ human_size(number, options = {})

number_to_human_size(1234567)

示例:

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

如文档 http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_to_ human_size

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文