(
num: number,
options: FormatOptions = {},
)
| 116 | * @throws {TypeError} If `num` is not a finite number. |
| 117 | */ |
| 118 | export function format( |
| 119 | num: number, |
| 120 | options: FormatOptions = {}, |
| 121 | ): string { |
| 122 | if (!Number.isFinite(num)) { |
| 123 | throw new TypeError(`Expected a finite number, got ${typeof num}: ${num}`); |
| 124 | } |
| 125 | |
| 126 | const UNITS_FIRSTLETTER = (options.bits ? "b" : "B") + "kMGTPEZY"; |
| 127 | |
| 128 | if (options.signed && num === 0) { |
| 129 | return ` 0 ${UNITS_FIRSTLETTER[0]}`; |
| 130 | } |
| 131 | |
| 132 | const prefix = num < 0 ? "-" : (options.signed ? "+" : ""); |
| 133 | num = Math.abs(num); |
| 134 | |
| 135 | const localeOptions = getLocaleOptions(options); |
| 136 | |
| 137 | if (num < 1) { |
| 138 | const numberString = toLocaleString(num, options.locale, localeOptions); |
| 139 | return prefix + numberString + " " + UNITS_FIRSTLETTER[0]; |
| 140 | } |
| 141 | |
| 142 | const exponent = Math.min( |
| 143 | Math.floor( |
| 144 | options.binary ? Math.log(num) / Math.log(1024) : Math.log10(num) / 3, |
| 145 | ), |
| 146 | UNITS_FIRSTLETTER.length - 1, |
| 147 | ); |
| 148 | num /= Math.pow(options.binary ? 1024 : 1000, exponent); |
| 149 | |
| 150 | if (!localeOptions) { |
| 151 | num = Number(num.toPrecision(3)); |
| 152 | } |
| 153 | |
| 154 | const numberString = toLocaleString( |
| 155 | num, |
| 156 | options.locale, |
| 157 | localeOptions, |
| 158 | ); |
| 159 | |
| 160 | let unit = UNITS_FIRSTLETTER[exponent]; |
| 161 | if (exponent > 0) { |
| 162 | unit += options.binary ? "i" : ""; |
| 163 | unit += options.bits ? "bit" : "B"; |
| 164 | } |
| 165 | |
| 166 | return prefix + numberString + " " + unit; |
| 167 | } |
| 168 | |
| 169 | function getLocaleOptions( |
| 170 | { maximumFractionDigits, minimumFractionDigits }: FormatOptions, |
no test coverage detected