0

I'd like a JavaScript function to convert numbers to significant figures w/ suffixes. For example, 12,345 could return 12.3K, while 1,000,000 could return 1.00M.

Max Ghenis
  • 14,783
  • 16
  • 84
  • 132
  • Is the objection here that I'm asking about an Apps Script-compatible implementation of a JS function? I can remove references to Apps Script if preferred. – Max Ghenis Aug 22 '14 at 19:55
  • Apps Script references removed, please reconsider. – Max Ghenis Aug 24 '14 at 16:57
  • The objection is that you're either asking us to recommend a JavaScript library that already does this type of formatting (I'm sure there will be one, but you should use a search engine to find it instead of asking here) or you're asking us to write some code for you. People here will be happy to help if you have a go at writing this yourself and encounter bugs with your implementation, but won't just write the code for you. – Matthew Strawbridge Aug 24 '14 at 17:33
  • A Google search for queries like [javascript number format k m b t significant figures] were not helpful here. I've found lots (if not the majority) of SO answers to either reference libraries that solve the problem or writing full functions, e.g. this very similar question asked in Java: http://stackoverflow.com/questions/4753251/how-to-go-about-formatting-1200-to-1-2k-in-java I've written full functions to answer questions myself - snippets are often much less helpful. – Max Ghenis Aug 24 '14 at 17:48

1 Answers1

2

See this function and associated tests, also implemented in this Apps Script file container-bound to this spreadsheet:

// Calculates significant figures with suffixes K/M/B/T, e.g. 1234 = 1.23K
function sigfig(num, sigfigs_opt) {
  // Set default sigfigs to 3
  sigfigs_opt = (typeof sigfigs_opt === "undefined") ? 3 : sigfigs_opt;
  // Only assigns sig figs and suffixes for numbers > 1
  if (num <= 1) return num.toPrecision(sigfigs_opt);
  // Calculate for numbers > 1
  var power10 = log10(num);
  var power10ceiling = Math.floor(power10) + 1;
  // 0 = '', 1 = 'K', 2 = 'M', 3 = 'B', 4 = 'T'
  var SUFFIXES = ['', 'K', 'M', 'B', 'T'];
  // 100: power10 = 2, suffixNum = 0, suffix = ''
  // 1000: power10 = 3, suffixNum = 1, suffix = 'K'
  var suffixNum = Math.floor(power10 / 3);
  var suffix = SUFFIXES[suffixNum];
  // Would be 1 for '', 1000 for 'K', 1000000 for 'M', etc.
  var suffixPower10 = Math.pow(10, suffixNum * 3);
  var base = num / suffixPower10;
  var baseRound = base.toPrecision(sigfigs_opt);
  return baseRound + suffix;
}

function log10(num) {
  // Per http://stackoverflow.com/questions/3019278/how-can-i-specify-the-base-for-math-log-in-javascript#comment29970629_16868744
  // Handles floating-point errors log10(1000) otherwise fails at (2.99999996)
  return (Math.round(Math.log(num) / Math.LN10 * 1e6) / 1e6);
}

// Tests for sigfig(num, sigfigs=3). Returns T/F indicating test pass/fail.
function sigfig_test() {
  if (sigfig(1) != '1.00') return false;
  if (sigfig(1, 2) != '1.0') return false;
  if (sigfig(1.2) != '1.20') return false;
  if (sigfig(1234.5) != '1.23K') return false;
  if (sigfig(1000) != '1.00K') return false;
  if (sigfig(1234567) != '1.23M') return false;
  if (sigfig(1234567890, 4) != '1.235B') return false;
  if (sigfig(1e12, 1) != '1T') return false;
  if (sigfig(0.999999) != '1.00') return false;
  if (sigfig(0.00000434, 2) != '0.0000043') return false;
  return true;
}
Max Ghenis
  • 14,783
  • 16
  • 84
  • 132