将文件大小以字节为单位转换为人类可读的字符串

我使用这个函数将文件大小(以字节为单位)转换为人类可读的文件大小:

function getReadableFileSizeString(fileSizeInBytes) {
var i = -1;
var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
do {
fileSizeInBytes /= 1024;
i++;
} while (fileSizeInBytes > 1024);


return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
}


console.log(getReadableFileSizeString(1551859712)); // output is "1.4 GB"

然而,这似乎不是百分之百准确的。例如:

getReadableFileSizeString(1551859712); // output is "1.4 GB"

它不应该是"1.5 GB"吗?除以1024似乎失去了精度。是我完全误解了什么,还是有更好的办法?

167659 次浏览

这取决于你是想使用二进制还是十进制约定。

例如,RAM总是用二进制来度量,因此将1551859712表示为~1.4GiB是正确的。

另一方面,硬盘制造商喜欢使用十进制,所以他们称它为~1.6GB。

只是让人迷惑的是,软盘混合使用了这两种系统——它们的1MB实际上是1024000字节。

1551859712 / 1024 = 1515488
1515488 / 1024 = 1479.96875
1479.96875 / 1024 = 1.44528198242188

你的解决方法是正确的。要意识到的重要事情是,为了从15518597121.5,你必须除以1000,但是字节是以二进制到十进制的1024块来计数的,这就是为什么gb的值更小。

这是我写的一个:

/**
* Format bytes as human-readable text.
*
* @param bytes Number of bytes.
* @param si True to use metric (SI) units, aka powers of 1000. False to use
*           binary (IEC), aka powers of 1024.
* @param dp Number of decimal places to display.
*
* @return Formatted string.
*/
function humanFileSize(bytes, si=false, dp=1) {
const thresh = si ? 1000 : 1024;


if (Math.abs(bytes) < thresh) {
return bytes + ' B';
}


const units = si
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
let u = -1;
const r = 10**dp;


do {
bytes /= thresh;
++u;
} while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);




return bytes.toFixed(dp) + ' ' + units[u];
}




console.log(humanFileSize(1551859712))  // 1.4 GiB
console.log(humanFileSize(5000, true))  // 5.0 kB
console.log(humanFileSize(5000, false))  // 4.9 KiB
console.log(humanFileSize(-10000000000000000000000000000))  // -8271.8 YiB
console.log(humanFileSize(999949, true))  // 999.9 kB
console.log(humanFileSize(999950, true))  // 1.0 MB
console.log(humanFileSize(999950, true, 2))  // 999.95 kB
console.log(humanFileSize(999500, true, 0))  // 1 MB

下面是一个将数字转换为符合新的国际标准的可读字符串的原型。

有两种方法来表示大数字:你可以显示 它们的倍数1000 = 10 3(以10为基数)或1024 = 2 10(以2为基数) 除以1000,你可能会用SI前缀名,如果你 除以1024,你可能会使用IEC前缀名。这个问题 首先除以1024。许多应用程序使用SI前缀 它的名称和一些使用IEC前缀名称。现状 是一团糟。如果你看到SI前缀名,你不知道是否 数字除以1000或1024

https://wiki.ubuntu.com/UnitsPolicy < a href = " https://wiki.ubuntu.com/UnitsPolicy " > < / >

< a href = " http://en.wikipedia.org/wiki/Template Quantities_of_bytes”> http://en.wikipedia.org/wiki/Template Quantities_of_bytes < / >

Object.defineProperty(Number.prototype,'fileSize',{value:function(a,b,c,d){
return (a=a?[1e3,'k','B']:[1024,'K','iB'],b=Math,c=b.log,
d=c(this)/c(a[0])|0,this/b.pow(a[0],d)).toFixed(2)
+' '+(d?(a[1]+'MGTPEZY')[--d]+a[2]:'Bytes');
},writable:false,enumerable:false});

这个函数不包含loop,所以它可能比其他一些函数快。

用法:

IEC前缀

console.log((186457865).fileSize()); // default IEC (power 1024)
//177.82 MiB
//KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB

如果前缀

console.log((186457865).fileSize(1)); //1,true for SI (power 1000)
//186.46 MB
//kB,MB,GB,TB,PB,EB,ZB,YB

我将IEC设置为默认值,因为我总是使用二进制模式来计算文件的大小…使用1024的幂


如果你只想在一个简短的线性函数中使用其中一个:

如果

function fileSizeSI(a,b,c,d,e){
return (b=Math,c=b.log,d=1e3,e=c(a)/c(d)|0,a/b.pow(d,e)).toFixed(2)
+' '+(e?'kMGTPEZY'[--e]+'B':'Bytes')
}
//kB,MB,GB,TB,PB,EB,ZB,YB

IEC

function fileSizeIEC(a,b,c,d,e){
return (b=Math,c=b.log,d=1024,e=c(a)/c(d)|0,a/b.pow(d,e)).toFixed(2)
+' '+(e?'KMGTPEZY'[--e]+'iB':'Bytes')
}
//KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB

用法:

console.log(fileSizeIEC(7412834521));

如果你有关于函数的问题尽管问

计算的另一个体现

function humanFileSize(size) {
var i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));
return (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
}

基于cocco的想法,这里有一个不太紧凑但希望更全面的例子。

<!DOCTYPE html>
<html>
<head>
<title>File info</title>


<script>
<!--
function fileSize(bytes) {
var exp = Math.log(bytes) / Math.log(1024) | 0;
var result = (bytes / Math.pow(1024, exp)).toFixed(2);


return result + ' ' + (exp == 0 ? 'bytes': 'KMGTPEZY'[exp - 1] + 'B');
}


function info(input) {
input.nextElementSibling.textContent = fileSize(input.files[0].size);
}
-->
</script>
</head>


<body>
<label for="upload-file"> File: </label>
<input id="upload-file" type="file" onchange="info(this)">
<div></div>
</body>
</html>
sizeOf = function (bytes) {
if (bytes == 0) { return "0.00 B"; }
var e = Math.floor(Math.log(bytes) / Math.log(1024));
return (bytes/Math.pow(1024, e)).toFixed(2)+' '+' KMGTP'.charAt(e)+'B';
}
< p > sizeOf (2054110009), < br > //=> "1.91 GB"

. < p > sizeOf (7054110), < br > //=> "6.73 MB"

.

sizeOf(3*1024*1024) //=> "3.00 MB"

.

这是我的-也适用于真正大的文件-_-

function formatFileSize(size)
{
var sizes = [' Bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB'];
for (var i = 1; i < sizes.length; i++)
{
if (size < Math.pow(1024, i)) return (Math.round((size/Math.pow(1024, i-1))*100)/100) + sizes[i-1];
}
return size;
}

解决方案作为ReactJS组件

Bytes = React.createClass({
formatBytes() {
var i = Math.floor(Math.log(this.props.bytes) / Math.log(1024));
return !this.props.bytes && '0 Bytes' || (this.props.bytes / Math.pow(1024, i)).toFixed(2) + " " + ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][i]
},
render () {
return (
<span>{ this.formatBytes() }</span>
);
}
});

<强>更新 对于那些使用es6的人来说,这里是同一个组件

的无状态版本
const sufixes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const getBytes = (bytes) => {
const i = Math.floor(Math.log(bytes) / Math.log(1024));
return !bytes && '0 Bytes' || (bytes / Math.pow(1024, i)).toFixed(2) + " " + sufixes[i];
};


const Bytes = ({ bytes }) => (<span>{ getBytes(bytes) }</span>);


Bytes.propTypes = {
bytes: React.PropTypes.number,
};

基于cocco的回答,但略有降级(老实说,那些我觉得舒服的被保留/添加),并且不显示后面的0,但仍然支持0,希望对其他人有用:

function fileSizeSI(size) {
var e = (Math.log(size) / Math.log(1e3)) | 0;
return +(size / Math.pow(1e3, e)).toFixed(2) + ' ' + ('kMGTPEZY'[e - 1] || '') + 'B';
}




// test:
document.write([0, 23, 4322, 324232132, 22e9, 64.22e12, 76.22e15, 64.66e18, 77.11e21, 22e24].map(fileSizeSI).join('<br>'));

另一个类似的例子

function fileSize(b) {
var u = 0, s=1024;
while (b >= s || -b >= s) {
b /= s;
u++;
}
return (u ? b.toFixed(1) + ' ' : b) + ' KMGTPEZY'[u] + 'B';
}

它所衡量的性能比其他具有相似特性的算法好得可以忽略不计。

Let bytes = 1024 * 10 * 10 * 10;

console.log (getReadableFileSizeString(字节)

将返回1000.0Кб而不是1MB

对于那些使用Angular的人来说,有一个名为angular-pipes的包,它有一个管道:

文件

import { BytesPipe } from 'angular-pipes';

使用

\{\{ 150 | bytes }} <!-- 150 B -->
\{\{ 1024 | bytes }} <!-- 1 KB -->
\{\{ 1048576 | bytes }} <!-- 1 MB -->
\{\{ 1024 | bytes: 0 : 'KB' }} <!-- 1 MB -->
\{\{ 1073741824 | bytes }} <!-- 1 GB -->
\{\{ 1099511627776 | bytes }} <!-- 1 TB -->
\{\{ 1073741824 | bytes : 0 : 'B' : 'MB' }} <!-- 1024 MB -->

链接到文档

我想要“文件管理器”行为(例如,Windows资源管理器),其中小数位数与数字大小成比例。似乎没有其他答案是这样的。

function humanFileSize(size) {
if (size < 1024) return size + ' B'
let i = Math.floor(Math.log(size) / Math.log(1024))
let num = (size / Math.pow(1024, i))
let round = Math.round(num)
num = round < 10 ? num.toFixed(2) : round < 100 ? num.toFixed(1) : round
return `${num} ${'KMGTPEZY'[i-1]}B`
}

下面是一些例子:

humanFileSize(0)          // "0 B"
humanFileSize(1023)       // "1023 B"
humanFileSize(1024)       // "1.00 KB"
humanFileSize(10240)      // "10.0 KB"
humanFileSize(102400)     // "100 KB"
humanFileSize(1024000)    // "1000 KB"
humanFileSize(12345678)   // "11.8 MB"
humanFileSize(1234567890) // "1.15 GB"

我发现@cocco的回答有趣,但有以下问题与它:

  1. 不要修改本机类型或你不拥有的类型
  2. 为人类编写干净、可读的代码,让最小化器为机器优化代码
  3. (对TypeScript用户的奖励)不能很好地使用TypeScript

打字稿:

 /**
* Describes manner by which a quantity of bytes will be formatted.
*/
enum ByteFormat {
/**
* Use Base 10 (1 kB = 1000 bytes). Recommended for sizes of files on disk, disk sizes, bandwidth.
*/
SI = 0,
/**
* Use Base 2 (1 KiB = 1024 bytes). Recommended for RAM size, size of files on disk.
*/
IEC = 1
}


/**
* Returns a human-readable representation of a quantity of bytes in the most reasonable unit of magnitude.
* @example
* formatBytes(0) // returns "0 bytes"
* formatBytes(1) // returns "1 byte"
* formatBytes(1024, ByteFormat.IEC) // returns "1 KiB"
* formatBytes(1024, ByteFormat.SI) // returns "1.02 kB"
* @param size The size in bytes.
* @param format Format using SI (Base 10) or IEC (Base 2). Defaults to SI.
* @returns A string describing the bytes in the most reasonable unit of magnitude.
*/
function formatBytes(
value: number,
format: ByteFormat = ByteFormat.SI
) {
const [multiple, k, suffix] = (format === ByteFormat.SI
? [1000, 'k', 'B']
: [1024, 'K', 'iB']) as [number, string, string]
// tslint:disable-next-line: no-bitwise
const exp = (Math.log(value) / Math.log(multiple)) | 0
// or, if you'd prefer not to use bitwise expressions or disabling tslint rules, remove the line above and use the following:
// const exp = value === 0 ? 0 : Math.floor(Math.log(value) / Math.log(multiple))
const size = Number((value / Math.pow(multiple, exp)).toFixed(2))
return (
size +
' ' +
(exp
? (k + 'MGTPEZY')[exp - 1] + suffix
: 'byte' + (size !== 1 ? 's' : ''))
)
}


// example
[0, 1, 1024, Math.pow(1024, 2), Math.floor(Math.pow(1024, 2) * 2.34), Math.pow(1024, 3), Math.floor(Math.pow(1024, 3) * 892.2)].forEach(size => {
console.log('Bytes: ' + size)
console.log('SI size: ' + formatBytes(size))
console.log('IEC size: ' + formatBytes(size, 1) + '\n')
});

我的回答可能晚了,但我想它会帮助到某人。

度量前缀:

/**
* Format file size in metric prefix
* @param fileSize
* @returns {string}
*/
const formatFileSizeMetric = (fileSize) => {
let size = Math.abs(fileSize);


if (Number.isNaN(size)) {
return 'Invalid file size';
}


if (size === 0) {
return '0 bytes';
}


const units = ['bytes', 'kB', 'MB', 'GB', 'TB'];
let quotient = Math.floor(Math.log10(size) / 3);
quotient = quotient < units.length ? quotient : units.length - 1;
size /= (1000 ** quotient);


return `${+size.toFixed(2)} ${units[quotient]}`;
};

二进制前缀:

/**
* Format file size in binary prefix
* @param fileSize
* @returns {string}
*/
const formatFileSizeBinary = (fileSize) => {
let size = Math.abs(fileSize);


if (Number.isNaN(size)) {
return 'Invalid file size';
}


if (size === 0) {
return '0 bytes';
}


const units = ['bytes', 'kiB', 'MiB', 'GiB', 'TiB'];
let quotient = Math.floor(Math.log2(size) / 10);
quotient = quotient < units.length ? quotient : units.length - 1;
size /= (1024 ** quotient);


return `${+size.toFixed(2)} ${units[quotient]}`;
};

例子:

// Metrics prefix
formatFileSizeMetric(0)      // 0 bytes
formatFileSizeMetric(-1)     // 1 bytes
formatFileSizeMetric(100)    // 100 bytes
formatFileSizeMetric(1000)   // 1 kB
formatFileSizeMetric(10**5)  // 10 kB
formatFileSizeMetric(10**6)  // 1 MB
formatFileSizeMetric(10**9)  // 1GB
formatFileSizeMetric(10**12) // 1 TB
formatFileSizeMetric(10**15) // 1000 TB


// Binary prefix
formatFileSizeBinary(0)     // 0 bytes
formatFileSizeBinary(-1)    // 1 bytes
formatFileSizeBinary(1024)  // 1 kiB
formatFileSizeBinary(2048)  // 2 kiB
formatFileSizeBinary(2**20) // 1 MiB
formatFileSizeBinary(2**30) // 1 GiB
formatFileSizeBinary(2**40) // 1 TiB
formatFileSizeBinary(2**50) // 1024 TiB

这是mpen回答的大小改进

function humanFileSize(bytes, si=false) {
let u, b=bytes, t= si ? 1000 : 1024;
['', si?'k':'K', ...'MGTPEZY'].find(x=> (u=x, b/=t, b**2<1));
return `${u ? (t*b).toFixed(1) : bytes} ${u}${!si && u ? 'i':''}B`;
}

function humanFileSize(bytes, si=false) {
let u, b=bytes, t= si ? 1000 : 1024;
['', si?'k':'K', ...'MGTPEZY'].find(x=> (u=x, b/=t, b**2<1));
return `${u ? (t*b).toFixed(1) : bytes} ${u}${!si && u ? 'i':''}B`;
}




// TEST
console.log(humanFileSize(5000));      // 4.9 KiB
console.log(humanFileSize(5000,true)); // 5.0 kB

简单而简短的“漂亮字节”;函数,而无需不必要的分数舍入。

事实上,因为数字大小应该是人类可读的,“千分之一”;展示不再是人类。

小数点后的位数默认为2,但可以在调用函数时修改其他值。常见的大多数显示是默认的小数点后2位。

代码很短,并使用了数字字符串三胞胎的方法。

// Simple Pretty Bytes with SI system
// Without fraction rounding


function numberPrettyBytesSI(Num=0, dec=2){
if (Num<1000) return Num+" Bytes";
Num =("0".repeat((Num+="").length*2%3)+Num).match(/.{3}/g);
return Number(Num[0])+"."+Num[1].substring(0,dec)+" "+"  kMGTPEZY"[Num.length]+"B";
}


console.log(numberPrettyBytesSI(0));
console.log(numberPrettyBytesSI(500));
console.log(numberPrettyBytesSI(1000));
console.log(numberPrettyBytesSI(15000));
console.log(numberPrettyBytesSI(12345));
console.log(numberPrettyBytesSI(123456));
console.log(numberPrettyBytesSI(1234567));
console.log(numberPrettyBytesSI(12345678));

到2020年,你可以使用文件大小的npm包,它支持IEC(功率1024,默认),SI(功率1000)和JEDEC(替代SI单位符号)格式。

npm install file-size


import filesize from "filesize";


// outputs: 186.46 MB
filesize(186457865).human('si');


// outputs: 177.82 MiB
filesize(186457865).human();

https://www.npmjs.com/package/file-size

这里有很多很棒的答案。但是如果你正在寻找一种非常简单的方法,并且你不介意流行的库,那么filesize https://www.npmjs.com/package/filesize是一个很好的解决方案

它有很多选项,用法也很简单。

filesize(265318); // "259.1 KB"

从他们优秀的例子中

要在投票的解决方案中动态调整小数的数量,将bytes.toFixed(dp)转换为数字,然后再转换回字符串,如下所示:

return Number(bytes.toFixed(dp)).toString() + " " + units[u];
这将显示100 GiB而不是100.00 GiB。 对问题在js中动态地toFixed()

的引用

@Andrew V的typescript版本用新的“模板文字类型”来回答;

export const humanFileSize = (bytes: number): `${number} ${'B' | 'KB' | 'MB' | 'GB' | 'TB'}` => {
const index = Math.floor(Math.log(bytes) / Math.log(1024));
return `${Number((bytes / Math.pow(1024, index)).toFixed(2)) * 1} ${(['B', 'KB', 'MB', 'GB', 'TB'] as const)[index]}`;
};

下面是另一个国际化的实现,用TypeScript编写:

const UNITS = ['byte', 'kilobyte', 'megabyte', 'gigabyte', 'terabyte', 'petabyte']
const BYTES_PER_KB = 1000




/**
* Format bytes as human-readable text.
*
* @param sizeBytes Number of bytes.
*
* @return Formatted string.
*/
export function humanFileSize(sizeBytes: number | bigint): string {
let size = Math.abs(Number(sizeBytes))


let u = 0
while(size >= BYTES_PER_KB && u < UNITS.length-1) {
size /= BYTES_PER_KB
++u
}


return new Intl.NumberFormat([], {
style: 'unit',
unit: UNITS[u],
unitDisplay: 'short',
maximumFractionDigits: 1,
}).format(size)
}

[]替换为类似fr的语言代码,以强制进行默认以外的本地化。

console.log(humanFileSize(0))
console.log(humanFileSize(9))
console.log(humanFileSize(99))
console.log(humanFileSize(999))
console.log(humanFileSize(1000))
console.log(humanFileSize(1001))
console.log(humanFileSize(1023))
console.log(humanFileSize(1024))
console.log(humanFileSize(1025))
console.log(humanFileSize(100_000))
console.log(humanFileSize(1_000_000))
console.log(humanFileSize(1_000_000_000))
console.log(humanFileSize(1_000_000_000_000))
console.log(humanFileSize(1_000_000_000_000_000))
console.log(humanFileSize(1_000_000_000_000_000_000))
// fr
0 o
9 o
99 o
999 o
1 ko
1 ko
1 ko
1 ko
1 ko
100 ko
1 Mo
1 Go
1 To
1 Po
1 000 Po


// en-US
0 byte
9 byte
99 byte
999 byte
1 kB
1 kB
1 kB
1 kB
1 kB
100 kB
1 MB
1 GB
1 TB
1 PB
1,000 PB

现在你可以让Intl.NumberFormat自动为你做单位转换。如。

const sizeFormatter = new Intl.NumberFormat([], {
style: 'unit',
unit: 'byte',
notation: "compact",
unitDisplay: "narrow",
})


console.log(sizeFormatter.format(0))
console.log(sizeFormatter.format(1))
console.log(sizeFormatter.format(999))
console.log(sizeFormatter.format(1000))
console.log(sizeFormatter.format(1023))
console.log(sizeFormatter.format(1024))
console.log(sizeFormatter.format(1024**2))
console.log(sizeFormatter.format(1024**3))
console.log(sizeFormatter.format(1024**4))
console.log(sizeFormatter.format(1024**5))
console.log(sizeFormatter.format(1024**6))

…但是单位有点奇怪。例如:1024**41.1BB,我猜是“十亿字节”;;我不认为有人会用它,即使它在技术上是正确的。

我只是晚了10年!对于es6

function humanReadableSize(bytes) {
let size = parseInt(data)
for (let unit of ['b', 'Kb', 'Mb', 'Gb']) {
if (size < 1024) return `${size.toFixed(2)} ${unit}`
size /= 1024.0
}
}

我写了一个大小转换函数,它也接受人类可读的格式。

JS

const bitBase = 8;
const suffixes = {
bit: 'b',
b: 'B',
kb: 'KB',
mb: 'MB',
gb: 'GB',
tb: 'TB',
};
const multipliers = {
bit: {
toBitHr: 1,
toB: 1 / bitBase,
toKB: 1 / (bitBase * 1e3),
toMB: 1 / (bitBase * 1e6),
toGB: 1 / (bitBase * 1e9),
toTB: 1 / (bitBase * 1e12),
},
B: {
toBit: bitBase,
toBHr: 1,
toKB: 1 / 1e3,
toMB: 1 / 1e6,
toGB: 1 / 1e9,
toTB: 1 / 1e12,
},
KB: {
toBit: 1 / (bitBase * 1e3),
toB: 1e3,
toKBHr: 1,
toMB: 1 / 1e3,
toGB: 1 / 1e6,
toTB: 1 / 1e9,
},
MB: {
toBit: bitBase * 1e6,
toB: 1e6,
toKB: 1e3,
toMBHr: 1,
toGB: 1 / 1e3,
toTB: 1 / 1e6,
},
GB: {
toBit: bitBase * 1e9,
toB: 1e9,
toKB: 1e6,
toMB: 1e3,
toGBHr: 1,
toTB: 1 / 1e3,
},
TB: {
toBit: bitBase * 1e12,
toB: 1e12,
toKB: 1e9,
toMB: 1e6,
toGB: 1e3,
toTBHr: 1,
},
};


const round = (num, decimalPlaces) => {
const strNum = num.toString();
const isExp = strNum.includes('e');
if (isExp) {
return Number(num.toPrecision(decimalPlaces + 1));
}


return Number(
`${Math.round(Number(`${num}e${decimalPlaces}`))}e${decimalPlaces * -1}`,
);
};


function conv(
value,
hr,
rnd,
multiplier,
suffix,
) {
let val = value * multiplier;
if ((value * multiplier) > Number.MAX_SAFE_INTEGER) {
val = Number.MAX_SAFE_INTEGER;
}
if (val < Number.MIN_VALUE) val = 0;
if ((rnd || rnd === 0) && val < Number.MAX_SAFE_INTEGER) {
val = round(val, rnd);
}
if (hr) return `${val}${suffix}`;
return val;
}


const MemConv = (function _() {
return {
bit(value) {
return {
toBitHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.bit.toBitHr,
suffixes.bit,
);
},
toB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.bit.toB,
suffixes.b,
);
},
toKB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.bit.toKB,
suffixes.kb,
);
},
toMB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.bit.toMB,
suffixes.mb,
);
},
toGB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.bit.toGB,
suffixes.gb,
);
},
toTB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.bit.toTB,
suffixes.tb,
);
},
};
},
B(value) {
return {
toBit(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.B.toBit,
suffixes.bit,
);
},
toBHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.B.toBHr,
suffixes.b,
);
},
toKB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.B.toKB,
suffixes.kb,
);
},
toMB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.B.toMB,
suffixes.mb,
);
},
toGB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.B.toGB,
suffixes.gb,
);
},
toTB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.B.toTB,
suffixes.tb,
);
},
};
},
KB(value) {
return {
toBit(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.KB.toBit,
suffixes.bit,
);
},
toB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.KB.toB,
suffixes.b,
);
},
toKBHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.KB.toKBHr,
suffixes.kb,
);
},
toMB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.KB.toMB,
suffixes.mb,
);
},
toGB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.KB.toGB,
suffixes.gb,
);
},
toTB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.KB.toTB,
suffixes.tb,
);
},
};
},
MB(value) {
return {
toBit(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.MB.toBit,
suffixes.bit,
);
},
toB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.MB.toB,
suffixes.b,
);
},
toKB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.MB.toKB,
suffixes.kb,
);
},
toMBHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.MB.toMBHr,
suffixes.mb,
);
},
toGB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.MB.toGB,
suffixes.gb,
);
},
toTB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.MB.toTB,
suffixes.tb,
);
},
};
},
GB(value) {
return {
toBit(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.GB.toBit,
suffixes.bit,
);
},
toB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.GB.toB,
suffixes.b,
);
},
toKB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.GB.toKB,
suffixes.kb,
);
},
toMB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.GB.toMB,
suffixes.mb,
);
},
toGBHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.GB.toGBHr,
suffixes.gb,
);
},
toTB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.GB.toTB,
suffixes.tb,
);
},
};
},
TB(value) {
return {
toBit(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.TB.toBit,
suffixes.bit,
);
},
toB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.TB.toB,
suffixes.b,
);
},
toKB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.TB.toKB,
suffixes.kb,
);
},
toMB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.TB.toMB,
suffixes.mb,
);
},
toGB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.TB.toGB,
suffixes.gb,
);
},
toTBHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.TB.toTBHr,
suffixes.tb,
);
},
};
},
};
}());


const testCases = [1, 10, 150, 1000, 74839.67346];
const HRSuffixes = Object.values(suffixes);
const roundDecimals = 2;
const precision = Number(`0.${'0'.repeat(roundDecimals)}5`);
const SCIENTIFIC_NOT_NUMBER_REGXP = /[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?/g;
const SUFFIX_REGXP = /[a-z]+$/i;
const CONVERSION_TO_REGXP = /(?<=to).*(?=hr+$)|(?<=to).*(?=hr+$)?/i;


for (const conversionFrom of (Object.keys(MemConv))) {
for (const tCase of testCases) {
const convFunc = MemConv[conversionFrom](tCase);
for (const [conversionToFn, f] of Object.entries(convFunc)) {
const conversionTo = (conversionToFn.match(CONVERSION_TO_REGXP) || [conversionToFn])[0];


const result = f();
const humanReadable = f({ hr: true });
const rounded = f({ round: roundDecimals });
const roundedAndHumanReadable = f({ hr: true, round: roundDecimals });




console.log({
value: tCase,
from: conversionFrom,
to: conversionTo,
result,
humanReadable,
rounded,
roundedAndHumanReadable,
});
}
}
}

< p > TSVersion

test

import assert from 'assert';


function test() {
const testCases = [1, 10, 150, 1000, 74839.67346];
const HRSuffixes = Object.values(suffixes);
const roundDecimals = 2;
const precision = Number(`0.${'0'.repeat(roundDecimals)}5`);
const SCIENTIFIC_NOT_NUMBER_REGXP = /[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?/g;
const SUFFIX_REGXP = /[a-z]+$/i;
const CONVERSION_TO_REGXP = /(?<=to).*(?=hr+$)|(?<=to).*(?=hr+$)?/i;


for (const conversionFrom of (Object.keys(MemConv) as (keyof typeof MemConv)[])) {
for (const tCase of testCases) {
const convFunc = MemConv[conversionFrom](tCase);
for (const [conversionToFn, f] of Object.entries(convFunc)) {
const conversionTo = (conversionToFn.match(CONVERSION_TO_REGXP) || [conversionToFn])[0];
const expectedSuffix = suffixes[conversionTo.toLowerCase() as keyof typeof suffixes];
const multiplier = multipliers[conversionFrom][conversionToFn as keyof typeof multipliers[typeof conversionFrom]];
const expectedResult = tCase * multiplier > Number.MAX_SAFE_INTEGER
? Number.MAX_SAFE_INTEGER
: tCase * multiplier;


const result = f();
const humanReadable = f({ hr: true });
const rounded = f({ round: roundDecimals });
const roundedAndHumanReadable = f({ hr: true, round: roundDecimals });


const resHrNumber = Number((humanReadable.match(SCIENTIFIC_NOT_NUMBER_REGXP) || [''])[0]);
const resHrSuffix = (humanReadable.match(SUFFIX_REGXP) || [0])[0];
const resRoundHrNumber = Number((roundedAndHumanReadable.match(SCIENTIFIC_NOT_NUMBER_REGXP) || [''])[0]);
const resRoundHrSuffix = (roundedAndHumanReadable.match(SUFFIX_REGXP) || [0])[0];


if (/hr$/i.test(conversionToFn)) {
const resNumber = Number((humanReadable.match(SCIENTIFIC_NOT_NUMBER_REGXP) || [''])[0]);
const resSuffix = (humanReadable.match(SUFFIX_REGXP) || [0])[0];
assert(typeof result === 'string');
assert(typeof resSuffix === 'string');
assert(typeof resRoundHrNumber === 'number');
assert(typeof rounded === 'string');
assert(result === humanReadable);
assert(resSuffix === expectedSuffix);
assert(resNumber <= expectedResult + precision && resNumber >= expectedResult - precision);
} else {
assert(typeof result === 'number');
assert(result === resHrNumber);
assert(typeof rounded === 'number');
assert(result <= expectedResult + precision && result >= expectedResult - precision);
}


console.log({
value: tCase,
from: conversionFrom,
to: conversionToFn,
result,
humanReadable,
rounded,
roundedAndHumanReadable,
});


assert(typeof resHrSuffix === 'string');
assert(typeof resHrNumber === 'number');
assert(resHrSuffix === expectedSuffix);
assert(resHrSuffix === resRoundHrSuffix);
assert(HRSuffixes.includes(resHrSuffix));
}
}
}
}
test();

Usage

// GB to GB humanReadable
console.log(MemConv.GB(11.1942).toGBHr()); // 11.1942GB;
// GB to MB
console.log(MemConv.GB(11.1942).toMB());// 11194.2;
// MB to MB humanReadable
console.log(MemConv.MB(11.1942).toGB({ hr: true }));// 0.011194200000000001GB;
// MB to MB humanReadable with rounding
console.log(MemConv.MB(11.1942).toGB({ hr: true, round: 3 }));// 0.011GB;