All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scout.util.numbers.js Maven / Gradle / Ivy

There is a newer version: 25.1.0-beta.0
Show newest version
/*******************************************************************************
 * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     BSI Business Systems Integration AG - initial API and implementation
 ******************************************************************************/
scout.numbers = {

  /**
   * Converts the given decimal number to base-62 (i.e. the same value, but
   * represented by [a-zA-Z0-9] instead of only [0-9].
   */
  toBase62: function(number) {
    if (number === undefined) {
      return undefined;
    }
    var symbols = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.split('');
    var base = 62;
    var s = '';
    var n;
    while (number >= 1) {
      n = Math.floor(number / base);
      s = symbols[(number - (base * n))] + s;
      number = n;
    }
    return s;
  },

  /**
   * Returns a random sequence of characters out of the set [a-zA-Z0-9] with the
   * given length. The default length is 8.
   */
  randomId: function(length) {
    length = length || 8;
    var alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    var result = '';
    for (var i = 0; i < length; i++) {
      result += alphabet[Math.floor(Math.random() * alphabet.length)];
    }
    return result;
  },

  _correlationCounter: 1,

  /**
   * Generates a random ID suitable for use as correlation ID.
   *
   * Example:
   *
   *   Hq5JY2kz3n/27
   *
   * The ID is generated from two different alphabets: 1. only letter, 2. only digits. By
   * always selecting a random digit after two random characters, accidental "rude words"
   * can be prevented.
   *
   * The characters[01olOL] are not used at all because they are easily confused.
   *
   * For a length of 11 (default), this method can theoretically generate over 200 trillion
   * different IDs:
   *
   *   46^7 * 8^3 = 223'138'640'494'592
   *
   * To further reduce the risk of collisions, a monotonically increasing counter is added
   * at the end of the result string (separated by "/").
   */
  correlationId: function(length) {
    length = length || 11;
    var letters = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ';
    var digits = '23456789';
    var result = '';
    for (var i = 0; i < length; i++) {
      if ((i + 1) % 3 === 0) {
        result += digits[Math.floor(Math.random() * digits.length)];
      } else {
        result += letters[Math.floor(Math.random() * letters.length)];
      }
    }
    return result + '/' + (this._correlationCounter++);
  },

  /**
   * Rounds a number to the given number of decimal places.
   *
   * Numbers should not be rounded with the built-in Number.toFixed() method, since it
   * behaves differently on different browsers. However, it is safe to apply toFixed()
   * to the result of this method to ensure a fixed number of decimal places (filled up
   * with 0's) because this operation does not involve any rounding anymore.
   * 

* If decimalPlaces is omitted, the number will be rounded to integer by default. * Rounding mode {@link scout.numbers.RoundingMode.HALF_UP} is used as default. */ round: function(number, roundingMode, decimalPlaces) { if (number === null || number === undefined) { return number; } decimalPlaces = decimalPlaces || 0; // Do _not_ multiply with powers of 10 here, because that might cause rounding errors! // Example: 1.005 with 2 decimal places would result in 100.49999999999999 number = this.shiftDecimalPoint(number, decimalPlaces); switch (roundingMode) { case scout.numbers.RoundingMode.UP: if (number < 0) { number = -Math.ceil(Math.abs(number)); } else { number = Math.ceil(number); } break; case scout.numbers.RoundingMode.DOWN: if (number < 0) { number = -Math.floor(Math.abs(number)); } else { number = Math.floor(number); } break; case scout.numbers.RoundingMode.CEILING: number = Math.ceil(number); break; case scout.numbers.RoundingMode.FLOOR: number = Math.floor(number); break; case scout.numbers.RoundingMode.HALF_DOWN: if (number < 0) { number = Math.round(number); } else { number = -Math.round(-number); } break; // case scout.numbers.RoundingMode.HALF_EVEN: // case scout.numbers.RoundingMode.UNNECESSARY: // not implemented, default is used. default: // scout.numbers.RoundingMode.HALF_UP is used as default if (number < 0) { number = -Math.round(Math.abs(number)); } else { number = Math.round(number); } } return this.shiftDecimalPoint(number, -decimalPlaces); }, /** * Shifts the decimal point in the given number by a certain distance. While the result is also * number, the method uses string operations to move the decimal point. This prevents rounding * errors as long as the number does not exceed JavaScript's Number precision. * * The argument 'move' describes the distance how far the decimal point should be moved: * 0 = do no move (1.57 --> 1.57) * > 0 = move to right (1.57 --> 15.7) * < 0 = move to left (1.57 --> 0.157) */ shiftDecimalPoint: function(number, move) { if (number === null || number === undefined || !move) { return number; } var sign = (number ? (number < 0 ? -1 : 1) : 0); var distance = Math.abs(move); number = Math.abs(number); var s = scout.strings.asString(number); var a; if (move < 0) { // move to left s = scout.strings.repeat('0', distance) + s; a = s.split('.', 2); if (a.length === 1) { s = s.substr(0, s.length - distance) + '.' + s.substr(s.length - distance); } else { s = a[0].substr(0, a[0].length - distance) + '.' + a[0].substr(a[0].length - distance) + a[1]; } } else if (move > 0) { // move to right s += scout.strings.repeat('0', distance); a = s.split('.', 2); if (a.length === 2) { s = a[0] + a[1].substr(0, distance) + '.' + a[1].substr(distance); } } // Remove multiple leading zeros to prevent interpretation as octal number s = s.replace(/^0*(\d)/g, '$1'); return Number(s) * sign; } }; /** * Enum providing rounding-modes for number columns and fields. * * @see RoundingMode.java */ scout.numbers.RoundingMode = { UP: 'UP', DOWN: 'DOWN', CEILING: 'CEILING', FLOOR: 'FLOOR', HALF_UP: 'HALF_UP', HALF_DOWN: 'HALF_DOWN', HALF_EVEN: 'HALF_EVEN', UNNECESSARY: 'UNNECESSARY' };





© 2015 - 2025 Weber Informatics LLC | Privacy Policy