format(number) {
    if (number === '') {
      return '';
    }

    const zeroSymbol = this.zeroSymbol();
    if (zeroSymbol !== undefined && zeroSymbol !== null && number === 0) {
      return zeroSymbol;
    }

    const nullSymbol = this.nullSymbol();
    if (nullSymbol !== undefined && nullSymbol !== null && number === null) {
      return nullSymbol;
    }

    const notANumberSymbol = this.notANumberSymbol();
    if (notANumberSymbol !== undefined && notANumberSymbol !== null && isNaN(number)) {
      return notANumberSymbol;
    }

    const positiveInfinitySymbol = this.positiveInfinitySymbol();
    if (positiveInfinitySymbol !== undefined && positiveInfinitySymbol !== null && number === Infinity) {
      return positiveInfinitySymbol;
    }

    const negativeInfinitySymbol = this.negativeInfinitySymbol();
    if (negativeInfinitySymbol !== undefined && negativeInfinitySymbol !== null && number === -Infinity) {
      return negativeInfinitySymbol;
    }

    let negative = number < 0;

    let parts = (''+Math.abs(number)).split('.');
    let integerPart = parts[0];
    let fractionPart = parts[1] || '';

    const exponent = this.exponent();
    if (exponent !== undefined && exponent !== null) {
      const shifted = shiftParts([negative, integerPart, fractionPart], exponent);
      negative = shifted[0];
      integerPart = shifted[1];
      fractionPart = shifted[2];
      while (integerPart[0] === '0') {
        integerPart = integerPart.slice(1);
      }
    }

    // round fraction part to the maximum length
    const maximumFractionDigits = this.maximumFractionDigits();
    if (fractionPart.length > maximumFractionDigits) {
      const unrounded = `${integerPart}.${fractionPart}`;
      let rounded = this._round(negative ? `-${unrounded}` : unrounded);
      if (rounded[0] === '-') {
        rounded = rounded.slice(1);
      }
      parts = rounded.split('.');
      integerPart = parts[0];
      fractionPart = parts[1] || '';
    }

    // right-pad fraction zeros up to the minimum length
    const minimumFractionDigits = this.minimumFractionDigits();
    while (fractionPart.length < minimumFractionDigits) {
      fractionPart += '0';
    }

    // left-pad integer zeros up to the minimum length
    const minimumIntegerDigits = this.minimumIntegerDigits();
    while (integerPart.length < minimumIntegerDigits) {
      integerPart = '0' + integerPart;
    }

    // eat any unneeded trailing zeros
    while (fractionPart.length > minimumFractionDigits && fractionPart.slice(-1) === '0') {
      fractionPart = fractionPart.slice(0, -1);
    }

    // left-truncate any integer digits over the maximum length
    const maximumIntegerDigits = this.maximumIntegerDigits();
    if (maximumIntegerDigits !== undefined && maximumIntegerDigits !== null && integerPart.length > maximumIntegerDigits) {
      integerPart = integerPart.slice(-maximumIntegerDigits);
    }

    // add the decimal separator
    if (fractionPart.length > 0 || this.alwaysShowsDecimalSeparator()) {
      fractionPart = this.decimalSeparator() + fractionPart;
    }

    if (this.usesGroupingSeparator()) {
      let integerPartWithGroupingSeparators = '';
      let copiedCharacterCount = 0;

      for (let i = integerPart.length - 1; i >= 0; i--) {
        if (copiedCharacterCount > 0 && copiedCharacterCount % this.groupingSize() === 0) {
          integerPartWithGroupingSeparators = this.groupingSeparator() + integerPartWithGroupingSeparators;
        }
        integerPartWithGroupingSeparators = integerPart[i] + integerPartWithGroupingSeparators;
        copiedCharacterCount++;
      }
      integerPart = integerPartWithGroupingSeparators;
    }

    let result = integerPart + fractionPart;

    // surround with the appropriate prefix and suffix
    if (negative) {
      result = this.negativePrefix() + result + this.negativeSuffix();
    } else {
      result = this.positivePrefix() + result + this.positiveSuffix();
    }
    return result;
  }
Formats the given number as a string according to the settings applied to
this formatter. This may cause the number to be truncated, rounded, or
otherwise differ from what you might expect.

@example

  // By default no fraction digits are shown.
  var f = new FieldKit.NumberFormatter();
  f.format(Math.PI);  // '3'

  // Let's format as a currency.
  f.setNumberStyle(FieldKit.NumberFormatter.Style.CURRENCY);
  f.format(Math.PI);  // '$3.14'

  // Or as a percentage, which illustrates usage of {@link NumberFormatter#exponent}.
  f.setNumberStyle(FieldKit.NumberFormatter.Style.PERCENT);
  f.format(Math.PI);  // '314%'

  // For the rest of the examples we'll go back to normal.
  f.setNumberStyle(FieldKit.NumberFormatter.Style.NONE);

  // The default rounding mode is {@link NumberFormatter.Rounding.HALF_EVEN}.
  f.setMaximumFractionDigits(4);
  f.format(Math.PI);  // '3.1416'

  // And we can change the rounding mode if we like.
  f.setRoundingMode(FieldKit.NumberFormatter.Rounding.FLOOR);
  f.format(Math.PI);  // '3.1415'

@param {number} number
@returns {string}