我需要显示一个货币值的格式1K等于一千,或1.1K, 1.2K, 1.9K等,如果它不是一个偶数千,否则如果低于一千,显示正常500,100,250等,使用JavaScript格式化的数字?


当前回答

如果你喜欢,就把功劳归于韦伦·弗林

这比他处理负数和“。0”的情况。

循环和“如果”情况越少,IMO就越好。

function abbreviateNumber(number) {
    const SI_POSTFIXES = ["", "k", "M", "G", "T", "P", "E"];
    const sign = number < 0 ? '-1' : '';
    const absNumber = Math.abs(number);
    const tier = Math.log10(absNumber) / 3 | 0;
    // if zero, we don't need a prefix
    if(tier == 0) return `${absNumber}`;
    // get postfix and determine scale
    const postfix = SI_POSTFIXES[tier];
    const scale = Math.pow(10, tier * 3);
    // scale the number
    const scaled = absNumber / scale;
    const floored = Math.floor(scaled * 10) / 10;
    // format number and add postfix as suffix
    let str = floored.toFixed(1);
    // remove '.0' case
    str = (/\.0$/.test(str)) ? str.substr(0, str.length - 2) : str;
    return `${sign}${str}${postfix}`;
}

jsFiddle测试用例-> https://jsfiddle.net/qhbrz04o/9/

其他回答

这是非常优雅的。

function formatToUnits(number, precision) {
  const abbrev = ['', 'k', 'm', 'b', 't'];
  const unrangifiedOrder = Math.floor(Math.log10(Math.abs(number)) / 3)
  const order = Math.max(0, Math.min(unrangifiedOrder, abbrev.length -1 ))
  const suffix = abbrev[order];

  return (number / Math.pow(10, order * 3)).toFixed(precision) + suffix;
}

formatToUnits(12345, 2)
==> "12.35k"
formatToUnits(0, 3)
==> "0.000"

Waylon flynn的答案的修改版本,支持负指数:

function metric(number) { const SI_SYMBOL = [ ["", "k", "M", "G", "T", "P", "E"], // + ["", "m", "μ", "n", "p", "f", "a"] // - ]; const tier = Math.floor(Math.log10(Math.abs(number)) / 3) | 0; const n = tier < 0 ? 1 : 0; const t = Math.abs(tier); const scale = Math.pow(10, tier * 3); return { number: number, symbol: SI_SYMBOL[n][t], scale: scale, scaled: number / scale } } function metric_suffix(number, precision) { const m = metric(number); return (typeof precision === 'number' ? m.scaled.toFixed(precision) : m.scaled) + m.symbol; } for (var i = 1e-6, s = 1; i < 1e7; i *= 10, s *= -1) { // toggles sign in each iteration console.log(metric_suffix(s * (i + i / 5), 1)); } console.log(metric(0));

预期的输出:

   1.2μ
 -12.0μ
 120.0μ
  -1.2m
  12.0m
-120.0m
   1.2
 -12.0
 120.0
  -1.2k
  12.0k
-120.0k
   1.2M
{ number: 0, symbol: '', scale: 1, scaled: 0 }
/**
 * Shorten number to thousands, millions, billions, etc.
 * http://en.wikipedia.org/wiki/Metric_prefix
 *
 * @param {number} num Number to shorten.
 * @param {number} [digits=0] The number of digits to appear after the decimal point.
 * @returns {string|number}
 *
 * @example
 * // returns '12.5k'
 * shortenLargeNumber(12543, 1)
 *
 * @example
 * // returns '-13k'
 * shortenLargeNumber(-12567)
 *
 * @example
 * // returns '51M'
 * shortenLargeNumber(51000000)
 *
 * @example
 * // returns 651
 * shortenLargeNumber(651)
 *
 * @example
 * // returns 0.12345
 * shortenLargeNumber(0.12345)
 */
function shortenLargeNumber(num, digits) {
    var units = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'],
        decimal;

    for(var i=units.length-1; i>=0; i--) {
        decimal = Math.pow(1000, i+1);

        if(num <= -decimal || num >= decimal) {
            return +(num / decimal).toFixed(digits) + units[i];
        }
    }

    return num;
}

谢谢@Cos的评论,我删除了Math。round10依赖。

最多支持数量。MAX_SAFE_INTEGER到Number。MIN_SAFE_INTEGER

function abbreviateThousands(value) { const num = Number(value) const absNum = Math.abs(num) const sign = Math.sign(num) const numLength = Math.round(absNum).toString().length const symbol = ['K', 'M', 'B', 'T', 'Q'] const symbolIndex = Math.floor((numLength - 1) / 3) - 1 const abbrv = symbol[symbolIndex] || symbol[symbol.length - 1] let divisor = 0 if (numLength > 15) divisor = 1e15 else if (numLength > 12) divisor = 1e12 else if (numLength > 9) divisor = 1e9 else if (numLength > 6) divisor = 1e6 else if (numLength > 3) divisor = 1e3 else return num return `${((sign * absNum) / divisor).toFixed(divisor && 1)}${abbrv}` } console.log(abbreviateThousands(234523452345)) // 234.5b (billion) console.log(abbreviateThousands(Number.MIN_SAFE_INTEGER)) // -9.0q (quadrillion)

不满足任何张贴的解决方案,所以这是我的版本:

Supports positive and negative numbers Supports negative exponents Rounds up to next exponent if possible Performs bounds checking (doesn't error out for very large/small numbers) Strips off trailing zeros/spaces Supports a precision parameter function abbreviateNumber(number,digits=2) { var expK = Math.floor(Math.log10(Math.abs(number)) / 3); var scaled = number / Math.pow(1000, expK); if(Math.abs(scaled.toFixed(digits))>=1000) { // Check for rounding to next exponent scaled /= 1000; expK += 1; } var SI_SYMBOLS = "apμm kMGTPE"; var BASE0_OFFSET = SI_SYMBOLS.indexOf(' '); if (expK + BASE0_OFFSET>=SI_SYMBOLS.length) { // Bound check expK = SI_SYMBOLS.length-1 - BASE0_OFFSET; scaled = number / Math.pow(1000, expK); } else if (expK + BASE0_OFFSET < 0) return 0; // Too small return scaled.toFixed(digits).replace(/(\.|(\..*?))0+$/,'$2') + SI_SYMBOLS[expK+BASE0_OFFSET].trim(); } ////////////////// const tests = [ [0.0000000000001,2], [0.00000000001,2], [0.000000001,2], [0.000001,2], [0.001,2], [0.0016,2], [-0.0016,2], [0.01,2], [1,2], [999.99,2], [999.99,1], [-999.99,1], [999999,2], [999999999999,2], [999999999999999999,2], [99999999999999999999,2], ]; for (var i = 0; i < tests.length; i++) { console.log(abbreviateNumber(tests[i][0], tests[i][1]) ); }