Formatee un número como 2.5K si es mil o más, de lo contrario 900

154

Necesito mostrar un valor de moneda en el formato de 1K igual a mil, o 1.1K, 1.2K, 1.9K, etc., si no es incluso miles, de lo contrario si es inferior a mil, mostrar 500, 100, 250, etc. normal , usando javascript para formatear el número?

Carl Weis
fuente
2
¿También necesitas My G?
Salman A
Necesitaré M sí ... ¿Me pueden ayudar?
Carl Weis

Respuestas:

209

Parece que esto debería funcionar para usted:

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
fuente
2
Arreglo menor sugerido ... Debe ser minúscula k para miles. Superior es para Kilos. Intenté editar, pero requiere que se cambien al menos 6 caracteres antes de que tome.
Adam Youngers
¿Cómo inserto una variable php aquí y la uso? es decir, si mi variable de número es ¿ $mynumber_outputdónde inserto esto para usarlo? Por ejemplo, digamos $mynumber_output= 12846, me gustaría convertir 12846 a12.8k
Tenga en cuenta que un kilobyte es 1024 bytes en algunos casos: en.wikipedia.org/wiki/Kilobyte
Olle Härstedt
¿Alguna idea de cómo podemos hacer que 1000 se muestre como 1.0k en lugar de 1k?
Brent
1
No responde completamente la pregunta del usuario. "Necesitaré M sí ... ¿Puedes ayudar?" - Carl Weis
tfmontague
217

Una versión más generalizada:

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
fuente
@SalmanA: gran ayuda, falla si se pasa arg como cadena, si se limpia con parseFloat funciona bien. ¡Gracias!
Adesh M
1
Pequeña corrección para números menos <1000, agregue {valor: 1E0, símbolo: ""} a var si =
Dimmduh
1
@GiovanniAzua simplemente reemplaza if (num >= si[i].value)conif (Math.abs(num) >= si[i].value)
Salman A
¿qué .replace(rx, "$1")hacer?
M.Octavio
1
@ M.Octavio, la expresión regular se usa para recortar los ceros finales, por ejemplo, se 1.0convierte 1y se 1.10convierte1.1
Salman A
78

Aquí hay una solución simple que evita todas las ifdeclaraciones (con el poder 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é significa SI?

Waylon Flinn
fuente
Realmente me gusta tu solución. Para poder acortar también los valores negativos, multiplico el número por -1 antes y después de determinar el nivel, ya que Math.log10 (negativeValue) devolvería NaN.
xhadon
Sólo tiene que utilizar Math.abspara añadir soporte para números negativos, al igual que: var tier = Math.log10(Math.abs(number)) / 3 | 0;.
Caio Tarifa
71

Mejorando aún más la respuesta de Salman porque devuelve nFormatter (33000) como 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;
}

ahora nFormatter (33000) = 33K

Yash
fuente
2
De todos modos para hacer esto sin redondear el número? 1,590,000 devolverán 1.6M.
Brett Hardin
3
A veces es difícil saber cuándo publicar una nueva respuesta de editar una existente, algo que uso para decidir es que si robo el código de la respuesta de otro usuario, generalmente edito su respuesta para que puedan obtener el reconocimiento en lugar de que yo robe su código.
MH
@Yash, eres el código que estoy tratando de implementar en el script de contador, pero no obtengo este es mi enlace codepen codepen.io/Merajkhan/pen/MMoxGE?editors=1010 ¿ Me pueden ayudar a implementar esta lógica que quiero? Las unidades K, L, M tienen que venir.
Mehraj Khan
Excelente. Solución corta y dulce.
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;
}

Thx @Cos para comentar, eliminé la dependencia Math.round10.

Martin Sznapka
fuente
1
Puede cambiar el si a Math.abs(num) >= decimal.
Conor Pender
18

Muchas respuestas en este hilo se vuelven bastante complicadas, usando objetos matemáticos, objetos de mapas, bucles for, regex, etc. Pero estos enfoques realmente no mejoran la legibilidad del código o el rendimiento. Un enfoque directo parece ofrecer el mejor diseño.

Formateo del valor en efectivo con K

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

console.log(formatCash(2500));

Formateo del valor en efectivo con 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));

Usando números negativos

let format;
const number = -1235000;

if (number < 0) {
  format = '-' + formatCash(-1 * number);
} else {
  format = formatCash(number);
}
tfmontague
fuente
1
@ Jan - Actualicé mi publicación con un ejemplo, pero sentí que era lo suficientemente simple como para calcular la forma negativa usando'-' + formatCash(-1 * number)
tfmontague
15

Dale crédito a Waylon Flinn si te gusta esto

Esto se mejoró de su enfoque más elegante para manejar números negativos y el caso ".0".

Cuantos menos bucles y "if" tenga, mejor 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 con casos de prueba -> https://jsfiddle.net/xyug4nvz/7/

Jason Sebring
fuente
1
Todavía hay un error molesto: en abbreviateNumber(999999) == '1000k'lugar de '1M'. Esto se debe a que toFixed()también redondea los números. Sin embargo, no estoy seguro de cómo solucionarlo: /
Vitor Baptista
@VitorBaptista Si toFixed()redondea el número de todos modos, también puede redondear el número antes de enviarlo abbreviateNumber(), para que regrese en 1Mlugar de 1000k. No es una solución, sino una solución alternativa.
forsureitsme
2
Si no desea redondear, puede hacerlo después del paso de escala:const floored = Math.floor(scaled * 10) / 10;
tybro0103
14

ES2020 agrega soporte para esto al Intl.NumberFormatusar la notación de la siguiente manera:

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

NumberFormat especificaciones:

Tenga en cuenta que, por el momento, no todos los navegadores son compatibles con ES2020, por lo que puede necesitar este Polyfill: https://formatjs.io/docs/polyfills/intl-numberformat

Ori Price
fuente
Ese paquete ha quedado en desuso, así que utilice este enlace: npmjs.com/package/@formatjs/intl-numberformat
Ammad Khalid
2
Nota: Chrome admite notationy, compactDisplaypero FireFox 77 y Safari 13.1 aún no lo admiten, por lo que es probable que necesites el polyfill.
Josh Unger
Wow, Firefox acaba de agregar soporte para esto en v. 78, parece. Por supuesto, dentro de 2 años, este comentario se verá estúpido. : P (Sin embargo, es gracioso para mí porque el código se ejecuta para mí pero no se convierte correctamente, por lo que tendré que hacer una actualización.)
Andrew
11

Esto es bastante elegante.

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
fuente
4

Puede usar el paquete de formato d3 modelado después de Python Advanced String Formatting PEP3101 :

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

Mejorando aún más la respuesta de @ Yash con soporte de números negativos:

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"
fresa
fuente
3

Esta publicación es bastante antigua, pero de alguna manera llegué a esta publicación buscando algo. SO para agregar mi entrada Numeral js es la solución única ahora en días. Ofrece una gran cantidad de métodos para ayudar a formatear los números

http://numeraljs.com/

Vatsal
fuente
1
numeraljs ya no se mantiene. La horquilla más activa parece ser numbro . Pero ninguno de ellos apoya la notación SI / métrica
Vincent de Lagabbe
2

Método corto y genérico.

Puede hacer que el COUNT_FORMATSobjeto de configuración sea tan largo o corto como desee, dependiendo del rango de valores que esté probando.

// 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
fuente
1

Agregando en la respuesta superior, esto dará 1k por 1000 en lugar de 1.0k

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

Una versión modificada de la respuesta de Waylon Flinn con soporte para exponentes negativos:

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

Rendimiento esperado:

   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
fuente
1
  • Apoyo número negativo
  • Verificando para !Number.isFinite
  • Cambie ' K M G T P E Z Y'a ' K M'si desea que la unidad máxima seaM

El siguiente código es 1K = 1024, si desea 1K = 1000, cambie todos los 1024 a 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

Ala de acero
fuente
(11000) .prefix () equivale a 10.74K no muy preciso, debería decir 11.00K
bmaggi
1
@bmaggi Solo cambia el 1024 a 1000
Steely Wing
1

Mejorando aún más la respuesta de @ tfmontague para formatear lugares decimales. 33.0k a 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
fuente
1

No estoy satisfecho con ninguna de las soluciones publicadas, así que aquí está mi versión:

  1. Admite números positivos y negativos.
  2. Soporta exponentes negativos
  3. Redondea al siguiente exponente si es posible
  4. Realiza la comprobación de límites (no genera errores para números muy grandes / pequeños)
  5. Elimina los ceros / espacios finales
  6. Admite un parámetro de precisión

    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
fuente
1

Se me ocurrió uno muy codificado, ¡y es muy corto!

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

Craftingexpert1
fuente
1

Mejorando aún más la respuesta de Salman debido a casos como nFormatter (999999,1) que devuelve 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
fuente
1

La forma más simple y fácil de hacer esto es

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

Esto funciona para cualquier número. Incluyendo L Cretc.

Narasimha Reddy - Geeker
fuente
1

Al eliminar el bucle en la solución @ martin-sznapka, reducirá el tiempo de ejecución en un 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];

}

Prueba de velocidad (200000 muestras aleatorias) para una solución diferente de este hilo

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
fuente
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
fuente
por favor agregue alguna explicación de su solución
Harun Diluka Heshan
0

Esta función podría transformar grandes números (tanto positivos como negativos) en un formato amigable para el lector sin perder su precisión:

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
fuente
0

Estoy usando esta función. Funciona para ambos phpy 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;
    }
cha
fuente
0

Decidí ampliar mucho la respuesta de @ Novellizator aquí para satisfacer mis necesidades. Quería una función flexible para manejar la mayoría de mis necesidades de formato sin bibliotecas externas.

Caracteristicas

  • Opción para usar sufijos de orden (k, M, etc.)
    • Opción para especificar una lista personalizada de sufijos de orden para usar
    • Opción para restringir el orden mínimo y máximo
  • Control sobre el número de decimales
  • Comas automáticas de separación de pedidos
  • Formato opcional de porcentaje o dólar
  • Control sobre qué devolver en el caso de entrada no numérica
  • Funciona en números negativos e infinitos.

Ejemplos

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

Función

/*
 * 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 === '%' ? '%' : '');
}
Queso Marred
fuente
0

Wow, hay tantas respuestas aquí. Pensé en darte cómo lo resolví, ya que parecía ser el más fácil de leer, maneja números negativos y se aleja mucho en el rango de kilo de JavaScript. También sería fácil cambiar a lo que desea o ampliar aún más.

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
fuente
0

Una alternativa más corta:

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
fuente