web-dev-qa-db-fra.com

Formatez un nombre de 2,5 Ko s'il en existe plusieurs milliers, sinon 900

Je dois montrer une valeur monétaire au format 1K égale à mille, ou 1,1K, 1,2K, 1,9K, etc., si ce n'est pas même des milliers, sinon si moins de mille, affichez 500, 100, 250, etc. , en utilisant javascript pour formater le nombre?

96
Carl Weis

Cela devrait marcher pour vous:

function kFormatter(num) {
    return num > 999 ? (num/1000).toFixed(1) + 'k' : num
}

console.log(kFormatter(1200));
console.log(kFormatter(900));
147
Jake Feasel

Une version plus généralisée:

function nFormatter(num, digits) {
  var si = [
    { value: 1, symbol: "" },
    { value: 1E3, symbol: "k" },
    { value: 1E6, symbol: "M" },
    { value: 1E9, symbol: "G" },
    { value: 1E12, symbol: "T" },
    { value: 1E15, symbol: "P" },
    { value: 1E18, symbol: "E" }
  ];
  var rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
  var i;
  for (i = si.length - 1; i > 0; i--) {
    if (num >= si[i].value) {
      break;
    }
  }
  return (num / si[i].value).toFixed(digits).replace(rx, "$1") + si[i].symbol;
}

/*
 * Tests
 */
var tests = [
  { num: 1234, digits: 1 },
  { num: 100000000, digits: 1 },
  { num: 299792458, digits: 1 },
  { num: 759878, digits: 1 },
  { num: 759878, digits: 0 },
  { num: 123, digits: 1 },
  { num: 123.456, digits: 1 },
  { num: 123.456, digits: 2 },
  { num: 123.456, digits: 4 }
];
var i;
for (i = 0; i < tests.length; i++) {
  console.log("nFormatter(" + tests[i].num + ", " + tests[i].digits + ") = " + nFormatter(tests[i].num, tests[i].digits));
}

147
Salman A

Amélioration de la réponse de Salman car elle renvoie nFormatter (33000) à 33,0 Ko

function nFormatter(num) {
     if (num >= 1000000000) {
        return (num / 1000000000).toFixed(1).replace(/\.0$/, '') + 'G';
     }
     if (num >= 1000000) {
        return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
     }
     if (num >= 1000) {
        return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'K';
     }
     return num;
}

maintenant nFormatter (33000) = 33K

58
Yash

Voici une solution simple qui évite toutes les instructions if (avec le pouvoir de Math).

var SI_SYMBOL = ["", "k", "M", "G", "T", "P", "E"];

function abbreviateNumber(number){

    // what tier? (determines SI symbol)
    var tier = Math.log10(number) / 3 | 0;

    // if zero, we don't need a suffix
    if(tier == 0) return number;

    // get suffix and determine scale
    var suffix = SI_SYMBOL[tier];
    var scale = Math.pow(10, tier * 3);

    // scale the number
    var scaled = number / scale;

    // format number and add suffix
    return scaled.toFixed(1) + suffix;
}

Bonus Meme

Qu'est-ce que SI représente?

42
Waylon Flinn
/**
 * 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;
}

Merci @Cos pour le commentaire, j'ai supprimé la dépendance Math.round10.

17
Martin Sznapka

Donnez crédit à Waylon Flinn si vous aimez ça.

Cela a été amélioré par son approche plus élégante pour traiter les nombres négatifs et le cas ".0".

Moins il y a de boucles et de "si" cas, meilleure est l’OMI.

function abbreviateNumber(number) {
    var SI_POSTFIXES = ["", "k", "M", "G", "T", "P", "E"];
    var tier = Math.log10(Math.abs(number)) / 3 | 0;
    if(tier == 0) return number;
    var postfix = SI_POSTFIXES[tier];
    var scale = Math.pow(10, tier * 3);
    var scaled = number / scale;
    var formatted = scaled.toFixed(1) + '';
    if (/\.0$/.test(formatted))
      formatted = formatted.substr(0, formatted.length - 2);
    return formatted + postfix;
}

jsFiddle avec des cas de test -> https://jsfiddle.net/xyug4nvz/7/

9
Jason Sebring

c'est assez élégant.

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"
6
Novellizator

Améliorer encore la réponse de @ Yash avec un support de nombre négatif:

function nFormatter(num) {
    isNegative = false
    if (num < 0) {
        isNegative = true
    }
    num = Math.abs(num)
    if (num >= 1000000000) {
        formattedNumber = (num / 1000000000).toFixed(1).replace(/\.0$/, '') + 'G';
    } else if (num >= 1000000) {
        formattedNumber =  (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
    } else  if (num >= 1000) {
        formattedNumber =  (num / 1000).toFixed(1).replace(/\.0$/, '') + 'K';
    } else {
        formattedNumber = num;
    }   
    if(isNegative) { formattedNumber = '-' + formattedNumber }
    return formattedNumber;
}

nFormatter(-120000)
"-120K"
nFormatter(120000)
"120K"
4
Strawberry

Vous pouvez utiliser le paquet d3-format modélisé selon Python Advanced String Formatting PEP3101 :

var f = require('d3-format')
console.log(f.format('.2s')(2500)) // displays "2.5k"
3

Ce message est assez ancien, mais je suis parvenu à ce message à la recherche de quelque chose. SO pour ajouter mon entrée Numeral js est la solution unique maintenant plusieurs jours. Il donne un grand nombre de méthodes pour aider à formater les nombres

http://numeraljs.com/

1
Vatsal

Amélioration de la réponse de @ tfmontague pour mettre en forme les décimales. 33,0k à 33k

largeNumberFormatter(value: number): any {
   let result: any = value;

   if (value >= 1e3 && value < 1e6) { result = (value / 1e3).toFixed(1).replace(/\.0$/, '') + 'K'; }
   if (value >= 1e6 && value < 1e9) { result = (value / 1e6).toFixed(1).replace(/\.0$/, '') + 'M'; }
   if (value >= 1e9) { result = (value / 1e9).toFixed(1).replace(/\.0$/, '') + 'T'; }

   return result;
}
1
Abdul Rahman
  • Nombre négatif de soutien
  • Vérification de !Number.isFinite
  • Changez ' K M G T P E Z Y' en ' K M' si vous voulez que l'unité maximale soit M

Number.prototype.prefix = function (precision = 2) {

    var units = ' K M G T P E Z Y'.split(' ');

    if (this < 0) {
        return '-' + Math.abs(this).prefix(precision);
    }

    if (this < 1) {
        return this + units[0];
    }

    var power = Math.min(
        Math.floor(Math.log(this) / Math.log(1024)),
        units.length - 1
    );

    return (this / Math.pow(1024, power)).toFixed(precision) + units[power];
}

(10240).prefix() // 10.00K
(1234000).prefix(1) // 1.2M
(-10000).prefix() // -9.77K
0
Steely Wing
/*including negative values*/    
function nFormatter(num) {
      let neg = false;
       if(num < 0){
         num = num * -1;
         neg = true;
       }
       if (num >= 1000000000) {
         if(neg){
           return -1 * (num / 1000000000).toFixed(1).replace(/\.0$/, '') + 'G';  
         }
         return (num / 1000000000).toFixed(1).replace(/\.0$/, '') + 'G';
       }
       if (num >= 1000000) {
         if(neg){
           return -1 * (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';  
         }
         return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
       }
       if (num >= 1000) {
         if(neg){
           return -1 * (num / 1000).toFixed(1).replace(/\.0$/, '') + 'K';  
         }
         return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'K';
       }
       return num;
    }
0
vivek kumawat

Cette fonction pourrait transformer d’énormes nombres (positifs et négatifs) en un format convivial pour le lecteur sans perdre sa précision:

function abbrNum(n) {
    if (!n || (n && typeof n !== 'number')) {
      return '';
    }

    const ranges = [
      { divider: 1e12 , suffix: 't' },
      { divider: 1e9 , suffix: 'b' },
      { divider: 1e6 , suffix: 'm' },
      { divider: 1e3 , suffix: 'k' }
    ];
    const range = ranges.find(r => Math.abs(n) >= r.divider);
    if (range) {
      return (n / range.divider).toString() + range.suffix;
    }
    return n.toString();
}

/* test cases */
let testAry = [99, 1200, -150000, 9000000];
let resultAry = testAry.map(abbrNum);
console.log("result array: " + resultAry);
0
Hamzeen Hameem

En ajoutant la première réponse, cela donnera 1k pour 1000 au lieu de 1,0k

function kFormatter(num) {
    return num > 999 ? num % 1000 === 0 ? (num/1000).toFixed(0) + 'k' : (num/1000).toFixed(1) + 'k' : num
}
0
rajatbarman

Pas satisfait aucune des solutions postées, alors voici ma version:

  1. Prend en charge les nombres positifs et négatifs
  2. Prend en charge les exposants négatifs
  3. Arrondit au prochain exposant si possible
  4. Effectue la vérification des limites (ne pas sortir d'erreur pour les très grands/petits nombres)
  5. Élimine les zéros/espaces de fin
  6. Prend en charge un paramètre de précision

    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]) );
    }
0
ttk

Beaucoup de réponses sur ce fil deviennent assez compliquées, en utilisant des objets Math, des objets de carte, des boucles for-lo, des regex, etc. Mais ces approches n'améliorent pas vraiment la lisibilité du code, ni les performances. Une approche simple semble offrir le meilleur design.

Mise en forme de la valeur en espèces avec K

const formatCash = n => {
  if (n < 1e3) return n;
  if (n >= 1e3) return +(n / 1e3).toFixed(1) + "K";
};

console.log(formatCash(2500));

Mise en forme de la valeur en espèces avec K M B T

const formatCash = n => {
  if (n < 1e3) return n;
  if (n >= 1e3 && n < 1e6) return +(n / 1e3).toFixed(1) + "K";
  if (n >= 1e6 && n < 1e9) return +(n / 1e6).toFixed(1) + "M";
  if (n >= 1e9 && n < 1e12) return +(n / 1e9).toFixed(1) + "B";
  if (n >= 1e12) return +(n / 1e12).toFixed(1) + "T";
};

console.log(formatCash(1235000));
0
tfmontague

J'ai décidé de développer beaucoup la réponse de @ Novellizator ici pour répondre à mes besoins. Je souhaitais une fonction flexible pour gérer la plupart de mes besoins de formatage sans bibliothèques externes.

Caractéristiques

  • Option d'utilisation des suffixes d'ordre (k, M, etc.)
    • Option permettant de spécifier une liste personnalisée de suffixes de commande à utiliser
    • Option pour contraindre l'ordre min et max
  • Contrôle sur le nombre de décimales
  • Virgules de séparation d'ordre automatiques
  • Format facultatif en pourcentage ou en dollars
  • Contrôle sur ce qu'il faut retourner dans le cas d'une entrée non numérique
  • Fonctionne sur les nombres négatifs et infinis

Exemples

let x = 1234567.8;
formatNumber(x);  // '1,234,568'
formatNumber(x, {useOrderSuffix: true});  // '1M'
formatNumber(x, {useOrderSuffix: true, decimals: 3, maxOrder: 1});  // '1,234.568k'
formatNumber(x, {decimals: 2, style: '$'});  // '$1,234,567.80'

x = 10.615;
formatNumber(x, {style: '%'});  // '1,062%'
formatNumber(x, {useOrderSuffix: true, decimals: 1, style: '%'});  // '1.1k%'
formatNumber(x, {useOrderSuffix: true, decimals: 5, style: '%', minOrder: 2});  // '0.00106M%'

formatNumber(-Infinity);  // '-∞'
formatNumber(NaN);  // ''
formatNumber(NaN, {valueIfNaN: NaN});  // NaN

Une fonction

/*
 * Return the given number as a formatted string.  The default format is a plain
 * integer with thousands-separator commas.  The optional parameters facilitate
 * other formats:
 *   - decimals = the number of decimals places to round to and show
 *   - valueIfNaN = the value to show for non-numeric input
 *   - style
 *     - '%': multiplies by 100 and appends a percent symbol
 *     - '$': prepends a dollar sign
 *   - useOrderSuffix = whether to use suffixes like k for 1,000, etc.
 *   - orderSuffixes = the list of suffixes to use
 *   - minOrder and maxOrder allow the order to be constrained.  Examples:
 *     - minOrder = 1 means the k suffix should be used for numbers < 1,000
 *     - maxOrder = 1 means the k suffix should be used for numbers >= 1,000,000
 */
function formatNumber(number, {
    decimals = 0,
    valueIfNaN = '',
    style = '',
    useOrderSuffix = false,
    orderSuffixes = ['', 'k', 'M', 'B', 'T'],
    minOrder = 0,
    maxOrder = Infinity
  } = {}) {

  let x = parseFloat(number);

  if (isNaN(x))
    return valueIfNaN;

  if (style === '%')
    x *= 100.0;

  let order;
  if (!isFinite(x) || !useOrderSuffix)
    order = 0;
  else if (minOrder === maxOrder)
    order = minOrder;
  else {
    const unboundedOrder = Math.floor(Math.log10(Math.abs(x)) / 3);
    order = Math.max(
      0,
      minOrder,
      Math.min(unboundedOrder, maxOrder, orderSuffixes.length - 1)
    );
  }

  const orderSuffix = orderSuffixes[order];
  if (order !== 0)
    x /= Math.pow(10, order * 3);

  return (style === '$' ? '$' : '') +
    x.toLocaleString(
      'en-US',
      {
        style: 'decimal',
        minimumFractionDigits: decimals,
        maximumFractionDigits: decimals
      }
    ) +
    orderSuffix +
    (style === '%' ? '%' : '');
}
0
MarredCheese

Une version modifiée de la réponse de Waylon Flinn avec prise en charge des exposants négatifs:

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));

Production attendue:

   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 }
0
Thalionâth

J'utilise cette fonction. Cela fonctionne à la fois pour php et javascript.

    /**
     * @param $n
     * @return string
     * Use to convert large positive numbers in to short form like 1K+, 100K+, 199K+, 1M+, 10M+, 1B+ etc
     */
 function num_format($n) {
        $n_format = null;
        $suffix = null;
        if ($n > 0 && $n < 1000) {
           $n_format = Math.floor($n);   
            $suffix = '';
        }
        else if ($n == 1000) {
            $n_format = Math.floor($n / 1000);   //For PHP only use floor function insted of Math.floor()
            $suffix = 'K';
        }
        else if ($n > 1000 && $n < 1000000) {
            $n_format = Math.floor($n / 1000);
            $suffix = 'K+';
        } else if ($n == 1000000) {
            $n_format = Math.floor($n / 1000000);
            $suffix = 'M';
        } else if ($n > 1000000 && $n < 1000000000) {
            $n_format = Math.floor($n / 1000000);
            $suffix = 'M+';
        } else if ($n == 1000000000) {
            $n_format = Math.floor($n / 1000000000);
            $suffix = 'B';
        } else if ($n > 1000000000 && $n < 1000000000000) {
            $n_format = Math.floor($n / 1000000000);
            $suffix = 'B+';
        } else if ($n == 1000000000000) {
            $n_format = Math.floor($n / 1000000000000);
            $suffix = 'T';
        } else if ($n >= 1000000000000) {
            $n_format = Math.floor($n / 1000000000000);
            $suffix = 'T+';
        }


       /***** For PHP  ******/
       //  return !empty($n_format . $suffix) ? $n_format . $suffix : 0;

       /***** For Javascript ******/
        return ($n_format + $suffix).length > 0 ? $n_format + $suffix : 0;
    }
0
shah

Wow, il y a tellement de réponses ici. Je pensais pouvoir vous expliquer comment je l'avais résolu, car il semblait être le plus facile à lire, gère les nombres négatifs et sort loin dans la plage de nombres en kilos pour JavaScript. Il serait également facile de changer ce que vous voulez ou d’aller encore plus loin.

const symbols = [
  { value: 1, symbol: '' },
  { value: 1e3, symbol: 'k' },
  { value: 1e6, symbol: 'M' },
  { value: 1e9, symbol: 'G' },
  { value: 1e12, symbol: 'T' },
  { value: 1e15, symbol: 'P' },
  { value: 1e18, symbol: 'E' }
];

function numberFormatter(num, digits) {
  const numToCheck = Math.abs(num);
  for (let i = symbols.length - 1; i >= 0; i--) {
    if (numToCheck >= symbols[i].value) {
      const newNumber = (num / symbols[i].value).toFixed(digits);
      return `${newNumber}${symbols[i].symbol}`;
    }
  }
  return '0';
}

const tests = [
  { num: 1234, digits: 1 },
  { num: 100000000, digits: 1 },
  { num: 299792458, digits: 1 },
  { num: 759878, digits: 1 },
  { num: -759878, digits: 0 },
  { num: 123, digits: 1 },
  { num: 123.456, digits: 1 },
  { num: -123.456, digits: 2 },
  { num: 123.456, digits: 4 }
];
for (let i = 0; i < tests.length; i++) {
  console.log(`numberFormatter(${tests[i].num}, ${tests[i].digits})=${numberFormatter(tests[i].num, tests[i].digits)}`);
}
0
JT Turner