Formatez un nombre en 2,5K si mille ou plus, sinon 900

154

Je dois afficher une valeur de devise au format 1K égale à mille, ou 1,1K, 1,2K, 1,9K, etc., si ce n'est pas un millier pair, sinon si elle est inférieure à mille, affichez la normale 500, 100, 250, etc. , en utilisant javascript pour formater le nombre?

Carl Weis
la source
2
Avez-vous également besoin de Met G?
Salman A
J'aurai besoin de M oui ... Pouvez-vous m'aider?
Carl Weis

Réponses:

209

Cela devrait fonctionner pour vous:

function kFormatter(num) {
    return Math.abs(num) > 999 ? Math.sign(num)*((Math.abs(num)/1000).toFixed(1)) + 'k' : Math.sign(num)*Math.abs(num)
}
    
console.log(kFormatter(1200)); // 1.2k
console.log(kFormatter(-1200)); // -1.2k
console.log(kFormatter(900)); // 900
console.log(kFormatter(-900)); // -900

Jake Feasel
la source
2
Correction mineure suggérée ... Doit être un k minuscule pour des milliers. Upper est pour Kilos. Essayé de modifier, mais nécessite au moins 6 caractères modifiés avant de prendre.
Adam Youngers
Comment insérer une variable php ici et l'utiliser? c'est-à-dire si ma variable numérique est $mynumber_outputoù dois-je l'insérer pour l'utiliser? Par exemple, disons $mynumber_output= 12846, je voudrais que 12846 soit converti en12.8k
Notez qu'un kilo-octet
équivaut à
Une idée de la façon dont nous pouvons faire afficher 1000 comme 1.0k au lieu de 1k?
Brent
1
Ne répond pas complètement à la question de l'utilisateur. "J'aurai besoin de M oui ... Pouvez-vous m'aider?" - Carl Weis
tfmontague
217

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

Salman A
la source
@SalmanA - Grande aide, cela échoue si on passe arg en tant que chaîne, s'il est nettoyé avec parseFloat fonctionne bien. Je vous remercie!
Adesh M
1
Petite correction pour les nombres inférieurs à 1 000, ajoutez {value: 1E0, symbol: ""} à var si =
Dimmduh
1
@GiovanniAzua vient de remplacer if (num >= si[i].value)parif (Math.abs(num) >= si[i].value)
Salman A
que fait .replace(rx, "$1")-on?
M.Octavio
1
@ M.Octavio la regex est utilisée pour couper les zéros de fin, par exemple 1.0devient 1et 1.10devient1.1
Salman A
78

Voici une solution simple qui évite toutes les ifdéclarations (avec la puissance 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

Que fait SI ?

Waylon Flinn
la source
J'aime vraiment ta solution. Pour pouvoir raccourcir également les valeurs négatives, je multiplie le nombre par -1 avant et après la détermination du niveau, car Math.log10 (valeur négative) renverrait NaN.
xhadon
Il suffit d' utiliser Math.abspour ajouter le support aux nombres négatifs, comme ça: var tier = Math.log10(Math.abs(number)) / 3 | 0;.
Caio Tarifa le
71

Amélioration de la réponse de Salman car elle renvoie nFormatter (33000) sous la forme 33.0K

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

Yash
la source
2
Quoi qu'il en soit, faire cela sans arrondir le nombre? 1,590,000 renverra 1,6M.
Brett Hardin
3
Parfois, il est difficile de savoir quand publier une nouvelle réponse ou modifier une réponse existante, quelque chose que j'utilise pour décider est si je vole le code d'une autre réponse d'utilisateurs, je modifie généralement leur réponse afin qu'ils puissent obtenir la reconnaissance au lieu que je vole leur code.
MH le
@Yash, vous êtes le code que j'essaie d'implémenter dans le script de compteur mais je ne l'obtiens pas, c'est mon lien codepen.io/Merajkhan/pen/MMoxGE?editors=1010 Pouvez-vous m'aider à mettre en œuvre cette logique que je veux Les unités K, L, M doivent venir.
Mehraj Khan
Génial. Solution courte et douce.
Hasitha Jayawardana
22
/**
 * 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 commentaire, j'ai supprimé la dépendance Math.round10.

Martin Sznapka
la source
1
Vous pouvez modifier le if en Math.abs(num) >= decimal.
Conor Pender
18

Beaucoup de réponses sur ce thread deviennent plutôt compliquées, en utilisant des objets Math, des objets de carte, des boucles for, des expressions régulières, etc. Mais ces approches n'améliorent pas vraiment la lisibilité du code ou les performances. Une approche simple semble offrir le meilleur design.

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

Formatage de la valeur en espèces avec KMBT

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

Utiliser des nombres négatifs

let format;
const number = -1235000;

if (number < 0) {
  format = '-' + formatCash(-1 * number);
} else {
  format = formatCash(number);
}
tfmontague
la source
1
@Jan - Mise à jour de mon message avec un exemple, mais j'ai trouvé que c'était assez simple pour calculer la forme négative en utilisant'-' + formatCash(-1 * number)
tfmontague
15

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

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

Moins vous avez de boucles et de cas «si», 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/

Jason Sebring
la source
1
Il y a toujours un bug ennuyeux: abbreviateNumber(999999) == '1000k'au lieu de '1M'. C'est parce que toFixed()arrondit également les nombres. Je ne sais pas comment le résoudre, cependant: /
Vitor Baptista
@VitorBaptista Si toFixed()arrondit le nombre de toute façon, vous pouvez aussi arrondir le nombre avant de l'envoyer à abbreviateNumber(), afin qu'il retourne à la 1Mplace de 1000k. Pas une solution, mais une solution de contournement.
forsureitsme
2
Si vous ne voulez pas d'arrondi, vous pouvez le faire après l'étape de mise à l'échelle:const floored = Math.floor(scaled * 10) / 10;
tybro0103
14

ES2020 ajoute la prise en charge de cela dans Intl.NumberFormatUtilisation de la notation comme suit:

console.log(Intl.NumberFormat('en-US', { notation: "compact" , compactDisplay: "short" }).format(987654321));

NumberFormat spécifications:

Notez que pour le moment, tous les navigateurs ne prennent pas en charge ES2020, vous aurez donc peut-être besoin de ce Polyfill: https://formatjs.io/docs/polyfills/intl-numberformat

Prix ​​Ori
la source
Ce package est obsolète, veuillez donc utiliser ce lien: npmjs.com/package/@formatjs/intl-numberformat
Ammad Khalid
2
Remarque: Chrome prend en charge notationet, compactDisplaymais FireFox 77 et Safari 13.1 ne le prennent toujours pas en charge, vous aurez donc probablement besoin du polyfill.
Josh Unger le
Wow, Firefox vient d' ajouter le support pour cela dans la v. 78, semble-t-il. Bien sûr, dans 2 ans et plus, ce commentaire aura l'air stupide. : P (C'est drôle pour moi cependant parce que le code fonctionne pour moi mais il ne se convertit pas correctement, donc je vais devoir faire une mise à jour.)
Andrew
11

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"
Novellizator
la source
4

Vous pouvez utiliser le package au format d3 inspiré du formatage de chaîne avancé Python PEP3101 :

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

Améliorer encore la réponse de @ Yash avec la prise en charge des nombres négatifs:

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"
fraise
la source
3

Ce message est assez ancien mais j'ai en quelque sorte atteint ce message à la recherche de quelque chose. Donc, pour ajouter mon entrée Numeral js est la solution à guichet unique maintenant quelques jours. Il donne un grand nombre de méthodes pour aider à formater les nombres

http://numeraljs.com/

Vatsal
la source
1
numeraljs n'est plus maintenu. La fourche la plus active semble être numbro . Mais aucun d'eux ne supporte la notation SI / métrique
Vincent de Lagabbe
2

Méthode courte et générique

Vous pouvez rendre l' COUNT_FORMATSobjet de configuration aussi long ou court que vous le souhaitez, en fonction de la plage de valeurs que vous testez.

// Configuration    
const COUNT_FORMATS =
[
  { // 0 - 999
    letter: '',
    limit: 1e3
  },
  { // 1,000 - 999,999
    letter: 'K',
    limit: 1e6
  },
  { // 1,000,000 - 999,999,999
    letter: 'M',
    limit: 1e9
  },
  { // 1,000,000,000 - 999,999,999,999
    letter: 'B',
    limit: 1e12
  },
  { // 1,000,000,000,000 - 999,999,999,999,999
    letter: 'T',
    limit: 1e15
  }
];
    
// Format Method:
function formatCount(value)
{
  const format = COUNT_FORMATS.find(format => (value < format.limit));

  value = (1000 * value / format.limit);
  value = Math.round(value * 10) / 10; // keep one decimal number, only if needed

  return (value + format.letter);
}

// Test:
const test = [274, 1683, 56512, 523491, 9523489, 5729532709, 9421032489032];
test.forEach(value => console.log(`${ value } >>> ${ formatCount(value) }`));

Gil Epshtain
la source
1

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
}
Rajatbarman
la source
1

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 }
Thalionâth
la source
1
  • Soutenir le nombre négatif
  • Recherche de !Number.isFinite
  • Changez ' K M G T P E Z Y'pour ' K M'si vous voulez que l'unité maximale soitM

Le code ci-dessous est 1K = 1024, si vous voulez 1K = 1000, changez tous les 1024 en 1000.


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];
}

console.log('10240 = ' + (10240).prefix()) // 10.00K
console.log('1234000 = ' + (1234000).prefix(1)) // 1.2M
console.log('10000 = ' + (-10000).prefix()) // -9.77K

Aile de Steely
la source
(11000) .prefix () équivaut à 10,74K pas très précis devrait dire 11,00K
bmaggi
1
@bmaggi Il suffit de changer le 1024 en 1000
Steely Wing
1

Amélioration de la réponse de @ tfmontague pour formater 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;
}
Abdul Rahman
la source
1

Je ne suis satisfait d'aucune des solutions publiées, voici donc 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 génère pas d'erreur pour les très grands / petits nombres)
  5. Supprime 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]) );
    }

ttk
la source
1

J'en ai trouvé un très codé au golf, et il est très court!

var beautify=n=>((Math.log10(n)/3|0)==0)?n:Number((n/Math.pow(10,(Math.log10(n)/3|0)*3)).toFixed(1))+["","K","M","B","T",][Math.log10(n)/3|0];

console.log(beautify(1000))
console.log(beautify(10000000))

Expert artisanal1
la source
1

Amélioration de la réponse de Salman grâce aux cas comme nFormatter (999999,1) qui renvoie 1000K.

function formatNumberWithMetricPrefix(num, digits = 1) {
  const si = [
    {value: 1e18, symbol: 'E'},
    {value: 1e15, symbol: 'P'},
    {value: 1e12, symbol: 'T'},
    {value: 1e9, symbol: 'G'},
    {value: 1e6, symbol: 'M'},
    {value: 1e3, symbol: 'k'},
    {value: 0, symbol: ''},
  ];
  const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
  function divideNum(divider) {
    return (num / (divider || 1)).toFixed(digits);
  }

  let i = si.findIndex(({value}) => num >= value);
  if (+divideNum(si[i].value) >= 1e3 && si[i - 1]) {
    i -= 1;
  }
  const {value, symbol} = si[i];
  return divideNum(value).replace(rx, '$1') + symbol;
}
Podvalnyi Mikhail
la source
1

Le moyen le plus simple et le plus simple de procéder est

new Intl.NumberFormat('en-IN', { 
    notation: "compact",
    compactDisplay: "short",
    style: 'currency',
    currency: 'INR'
}).format(1000).replace("T", "K")

Cela fonctionne pour n'importe quel nombre. Y compris L Cretc.

Narasimha Reddy - Geeker
la source
1

En éliminant la boucle dans la solution @ martin-sznapka, vous réduirez le temps d'exécution de 40%.

function formatNum(num,digits) {
    let units = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
    let floor = Math.floor(Math.abs(num).toString().length / 3);
    let value=+(num / Math.pow(1000, floor))
    return value.toFixed(value > 1?digits:2) + units[floor - 1];

}

Test de vitesse (200000 échantillons aléatoires) pour une solution différente de ce fil

Execution time: formatNum          418  ms
Execution time: kFormatter         438  ms it just use "k" no "M".."T" 
Execution time: beautify           593  ms doesnt support - negatives
Execution time: shortenLargeNumber 682  ms    
Execution time: Intl.NumberFormat  13197ms 
Feras
la source
0
/*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;
    }
vivek kumawat
la source
pls ajouter une explication de votre solution
Harun Diluka Heshan
0

Cette fonction peut transformer des nombres énormes (positifs et négatifs) en un format convivial pour les lecteurs 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);

Hamzeen Hameem
la source
0

J'utilise cette fonction. Cela fonctionne pour les deux phpet 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;
    }
shah
la source
0

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

Caractéristiques

  • Option pour utiliser les suffixes de commande (k, M, etc.)
    • Option pour spécifier une liste personnalisée de suffixes de commande à utiliser
    • Option pour contraindre l'ordre minimum et maximum
  • Contrôle du nombre de décimales
  • Virgules de séparation automatique de l'ordre
  • Formatage en pourcentage ou en dollars facultatif
  • Contrôle de ce qu'il faut renvoyer en cas de saisie 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

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 === '%' ? '%' : '');
}
MarredFromage
la source
0

Wow, il y a tellement de réponses ici. Je pensais que je pourrais vous expliquer comment je l'ai résolu car il semblait être le plus facile à lire, gère les nombres négatifs et va loin dans la plage de nombres kilos pour JavaScript. Il serait également facile de changer ce que vous voulez ou d'étendre 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)}`);
}

JT Turner
la source
0

Une alternative plus courte:

function nFormatter(num) {
    const format = [
      { value: 1e18, symbol: 'E' },
      { value: 1e15, symbol: 'P' },
      { value: 1e12, symbol: 'T' },
      { value: 1e9, symbol: 'G' },
      { value: 1e6, symbol: 'M' },
      { value: 1e3, symbol: 'k' },
      { value: 1, symbol: '' },
    ];
    const formatIndex = format.findIndex((data) => num >= data.value);
    console.log(formatIndex)
    return (num / format[formatIndex === -1? 6: formatIndex].value).toFixed(2) + format[formatIndex === -1?6: formatIndex].symbol;
  }
  

wkwkwk
la source