UNPKG

numfmt

Version:

Full Excel style number formatting

73 lines (64 loc) 1.71 kB
import { round } from './round.js'; const zero = { total: 1, sign: 0, period: 0, int: 1, frac: 0 }; // returns the count of digits (including - and .) need to represent the number export default function numdec (value, incl_sign = true) { const v = Math.abs(value); // shortcut zero if (!v) { return zero; } const signSize = (incl_sign && value < 0) ? 1 : 0; const intPart = Math.floor(v); const intSize = Math.floor(Math.log10(v) + 1); let periodSize = 0; let fracSize = 0; // is not an integer if (intPart !== v) { periodSize = 1; // B: this has turned out to be much faster than all pure math // based solutions I was able to come up with ¯\_(ツ)_/¯ const n = String( round(v * (10 ** -intSize), 15) ); let f = n.length; let z = true; let i = 0; while (i <= n.length) { if (n[i] === '.') { // discount period f--; break; } else if (n[i] === '0' && z) { // leading zeros before period are discounted f--; } else { // non-zero digit z = false; } i++; } fracSize = f - intSize; if (fracSize < 0) { // the number is not representable [by Excel] // this would be something like 1000.0000000000001 // it would normally get truncated to 15 significant figures and // end up in the same place as the following does: fracSize = 0; periodSize = 0; } } return { total: signSize + Math.max(intSize, 1) + periodSize + fracSize, digits: Math.max(intSize, 0) + fracSize, sign: signSize, period: periodSize, int: Math.max(intSize, 1), frac: fracSize }; }