如果一千或更多,则将数字格式化为 2.5K,否则为 900

Posted

技术标签:

【中文标题】如果一千或更多,则将数字格式化为 2.5K,否则为 900【英文标题】:Format a number as 2.5K if a thousand or more, otherwise 900 【发布时间】:2012-03-16 17:24:35 【问题描述】:

我需要以1K 的格式显示等于一千的货币值,或者1.1K1.2K1.9K 等,如果它不是偶数千,否则如果低于一千,正常显示500100250等,用javascript格式化数字?

【问题讨论】:

你还需要MG吗? 我需要 M 是的...你能帮忙吗? 见***.com/questions/17633462/… 查看***.com/a/60988355/80428 了解区域设置友好的 ES2020 解决方案 【参考方案1】:

听起来应该适合你:

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

【讨论】:

建议进行次要修复...应该是小写的 k 表示数千。上部是公斤。已尝试编辑,但需要至少更改 6 个字符。 如何在这里插入一个php变量并使用它?即如果我的数字变量是$mynumber_output,我应该在哪里插入它来使用它?比如说$mynumber_output = 12846,我想把12846转换成12.8k 请注意,在某些情况下,一千字节是 1024 字节:en.wikipedia.org/wiki/Kilobyte 没有完全回答用户的问题。 “我需要 M 是的……你能帮忙吗?” - 卡尔·韦斯 Math.round(Math.abs(num)/100)/10 而不是 (Math.abs(num)/1000).toFixed(1) 所以打字稿很开心【参考方案2】:

更通用的版本:

function nFormatter(num, digits) 
  const lookup = [
     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" 
  ];
  const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
  var item = lookup.slice().reverse().find(function(item) 
    return num >= item.value;
  );
  return item ? (num / item.value).toFixed(digits).replace(rx, "$1") + item.symbol : "0";


/*
 * Tests
 */
const tests = [
   num: 0, digits: 1 ,
   num: 12, digits: 1 ,
   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 
];
tests.forEach(function(test) 
  console.log("nFormatter(" + test.num + ", " + test.digits + ") = " + nFormatter(test.num, test.digits));
);

【讨论】:

@SalmanA - 非常有帮助,如果将 arg 作为字符串传递,如果使用 parseFloat 清理效果很好,则会失败。谢谢! 对小于 1000 的数字的小修正,将 value: 1E0, symbol: "" 添加到 var si = @GiovanniAzua 只需将 if (num >= si[i].value) 替换为 if (Math.abs(num) >= si[i].value) @M.Octavio 正则表达式用于修剪尾随零,例如1.0 变为 11.10 变为 1.1 另外,在开头处理特殊情况可能会很好。 if(num === 0) 返回 0;【参考方案3】:

进一步改进 Salman's Answer,因为它返回 nFormatter(33000) 为 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;

现在 nFormatter(33000) = 33K

【讨论】:

无论如何要在不四舍五入的情况下做到这一点? 1,590,000 将返回 1.6M。 有时很难知道何时发布编辑现有答案的新答案,我用来决定的是,如果我从其他用户的答案中窃取代码,我通常会编辑他们的答案,以便他们可以获得认可,而不是我窃取他们的代码。 @Yash 你是我试图在计数器脚本中实现的代码,但没有得到这是我的 codepen 链接codepen.io/Merajkhan/pen/MMoxGE?editors=1010 你能帮我弄清楚如何实现这个我想要的逻辑 K, L,M单位必须来。【参考方案4】:

通过负数支持进一步改进@Yash 的答案:

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"

【讨论】:

【参考方案5】:
/**
 * 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 依赖项。

【讨论】:

你可以把if改成Math.abs(num) &gt;= decimal【参考方案6】:

这篇文章已经很老了,但我不知何故找到了这篇文章来寻找一些东西。所以添加我的输入数字 js 是现在的一站式解决方案。它提供了大量方法来帮助格式化数字

http://numeraljs.com/

【讨论】:

numeraljs 不再维护。最活跃的分叉似乎是numbro。但它们都不支持 SI/公制符号【参考方案7】:

您可以使用模仿 Python Advanced String Formatting PEP3101 的 d3-format 包:

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

【讨论】:

【参考方案8】:

这是一个避免所有if 语句的简单解决方案(具有Math 的强大功能)。

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

function abbreviateNumber(number)

    // what tier? (determines SI symbol)
    var tier = Math.log10(Math.abs(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;

奖励模因

What does SI stand for?

【讨论】:

我真的很喜欢你的解决方案。为了能够缩短负值,我在确定层之前和之后将数字乘以 -1,因为 Math.log10(negativeValue) 将返回 NaN。 只需使用Math.abs 来添加对负数的支持,例如:var tier = Math.log10(Math.abs(number)) / 3 | 0; 谢谢,我进行了更改以启用负数。 这是否像接受的答案一样工作,没有任何问题?【参考方案9】:

如果你喜欢,请给 Waylon Flinn 点赞

这比他处理负数和“.0”情况的更优雅的方法得到了改进。

您拥有的循环和“if”案例越少,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/

【讨论】:

还有一个恼人的错误:abbreviateNumber(999999) == '1000k' 而不是'1M'。这是因为toFixed() 也会对数字进行四舍五入。不过,不知道如何解决它:/ @VitorBaptista 如果toFixed() 无论如何都会对数字进行四舍五入,那么您最好在将数字发送到abbreviateNumber() 之前将其四舍五入,因此它返回1M 而不是1000k。不是解决方案,而是解决方法。 如果您不想四舍五入,您可以在缩放步骤之后执行此操作:const floored = Math.floor(scaled * 10) / 10; 对负数不能正常工作 @forsureitsme 抱歉,我已经有一年没看到这个了……我添加了您的更改。 wrx!【参考方案10】:

加上最重要的答案,这将为 1000 提供 1k 而不是 1.0k

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

【讨论】:

【参考方案11】:
/*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;
    

【讨论】:

请添加一些您的解决方案的解释【参考方案12】:

这很优雅。

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"

【讨论】:

【参考方案13】: 支持负数 检查!isFinite 如果您希望最大单位为M,请将' K M G T P E Z Y' 更改为' K M' 基础选项 (1K = 1000 / 1K = 1024)

Number.prototype.prefix = function (precision, base) 

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

  if (typeof precision === 'undefined') 
    precision = 2;
  

  if (typeof base === 'undefined') 
    base = 1000;
  

  if (this == 0 || !isFinite(this)) 
    return this.toFixed(precision) + units[0];
  

  var power = Math.floor(Math.log(Math.abs(this)) / Math.log(base));
  // Make sure not larger than max prefix
  power = Math.min(power, units.length - 1);

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

console.log('0 = ' + (0).prefix()) // 0.00
console.log('10000 = ' + (10000).prefix()) // 10.00K
console.log('1234000 = ' + (1234000).prefix(1)) // 1.2M
console.log('-10000 = ' + (-10240).prefix(1, 1024)) // -10.0K
console.log('-Infinity = ' + (-Infinity).prefix()) // -Infinity
console.log('NaN = ' + (NaN).prefix()) // NaN

【讨论】:

(11000).prefix() 等于 10.74K 不是很准确应该说 11.00K @bmaggi 把 1024 改成 1000【参考方案14】:

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

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 

【讨论】:

【参考方案15】:

此函数可以将大量数字(正数和负数)转换为易于阅读的格式,而不会丢失其精度:

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

【讨论】:

【参考方案16】:

直截了当的方法具有最佳的可读性,并且使用的内存最少。无需过度设计使用正则表达式、映射对象、数学对象、for 循环等。

用 K 格式化现金值

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

console.log(formatCash(2500));

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

使用负数

let format;
const number = -1235000;

if (number < 0) 
  format = '-' + formatCash(-1 * number);
 else 
  format = formatCash(number);

【讨论】:

@Jan - 用一个例子更新了我的帖子,但觉得用'-' + formatCash(-1 * number)计算负数形式很简单【参考方案17】:

我正在使用这个功能。它适用于phpjavascript

    /**
     * @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;
    

【讨论】:

【参考方案18】:

我决定在这里扩展@Novellizator 的答案以满足我的需求。我想要一个灵活的函数来处理我的大部分格式化需求,而无需外部库。

特点

使用订单后缀(k、M 等)的选项 用于指定要使用的自定义订单后缀列表的选项 限制最小和最大顺序的选项 控制小数位数 自动顺序分隔逗号 可选百分比或美元格式 控制在非数字输入情况下返回的内容 适用于负数和无限数

示例

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

功能

/*
 * 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 === '%' ? '%' : '');

【讨论】:

【参考方案19】:

进一步改进@tfmontague 的答案以格式化小数位。 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;

【讨论】:

【参考方案20】:

哇,这里有这么多答案。我想我会告诉你我是如何解决它的,因为它似乎是最容易阅读的,处理负数,并且在 JavaScript 的千数范围内很远​​。也可以轻松更改为您想要的内容或扩展得更远。

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

【讨论】:

【参考方案21】:

对发布的任何解决方案都不满意,所以这是我的版本:

    支持正数和负数 支持负指数 如果可能,向上舍入到下一个指数 执行边界检查(对于非常大/小的数字不会出错) 去除尾随的零/空格

    支持精度参数

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

【讨论】:

【参考方案22】:

我想出了一个非常适合打高尔夫球的代码,而且很短!

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

【讨论】:

【参考方案23】:

由于返回 1000K 的 nFormatter(999999,1) 之类的情况,进一步改进了 Salman's Answer。

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;

【讨论】:

【参考方案24】:

短而通用的方法

您可以根据需要将COUNT_FORMATS 配置对象设置为长或短。这取决于您测试的值的范围。

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

【讨论】:

【参考方案25】:

最简单的方法是

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

这适用于任何数字。包括LCr等。

注意:不能在 Safari 中工作。

【讨论】:

在 node.js 上根本不工作【参考方案26】:

ES2020 在Intl.NumberFormat 中添加了对此的支持,使用如下符号:

let formatter = Intl.NumberFormat('en',  notation: 'compact' );
// example 1
let million = formatter.format(1e6);
// example 2
let billion = formatter.format(1e9);
// print
console.log(million == '1M', billion == '1B');

请注意,如上所示,第二个示例生成 1B 而不是 1GNumberFormat 规格:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat https://tc39.es/ecma402#numberformat-objects

请注意,目前并非所有浏览器都支持 ES2020,因此您可能需要这个 Polyfill:https://formatjs.io/docs/polyfills/intl-numberformat

【讨论】:

该软件包已被弃用,请使用此链接:npmjs.com/package/@formatjs/intl-numberformat 注意:Chrome 支持 notationcompactDisplay 但 FireFox 77 和 Safari 13.1 仍然不支持它,因此您可能需要 polyfill。 哇,Firefox just 在 v. 78 中添加了对此的支持,看来。当然,从现在起 2 年多以后,这条评论看起来会很愚蠢。 :P(这对我来说很有趣,因为代码为我运行但它不能正确转换,所以我需要进行更新。) compact 存在一些问题,而且它非常灵活。 例如。对于德国契约,当你想要 M 代表百万时,它不会给出 M,而是德国特定的替代方案。 const number = 12453456.789; console.log(new Intl.NumberFormat('de-DE', style: 'currency', currency: 'EUR', notation:'compact' ).format(number)); // 12 Mio。欧元【参考方案27】:

通过消除@martin-sznapka 解决方案中的循环,您将减少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];


此线程中不同解决方案的速度测试(200000 个随机样本)

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 

【讨论】:

【参考方案28】:

一个更短的替代方案:

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;
  
  

【讨论】:

【参考方案29】:

最高支持Number.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)

【讨论】:

【参考方案30】:

这是我对 Waylon Flinn 的回答的版本。当层不完全是整数时,这将删除 .0 并修复未定义。

const SI_SYMBOL = ['', 'k', 'M', 'G', 'T', 'P', 'E'];

abbreviateNumber(num) 
    const tier = Math.floor(Math.log10(num) / 3) || 0;
    let result = '' + num;
    // if zero, we don't need a suffix
    if (tier > 0) 
      // get suffix and determine scale
      const suffix = SI_SYMBOL[tier];
      const scale = Math.pow(10, tier * 3);
      // scale the number
      const scaled = num / scale;
      // format number and add suffix
      result = scaled.toFixed(1).replace('.0', '') + suffix;
    
    return result;
  

【讨论】:

以上是关于如果一千或更多,则将数字格式化为 2.5K,否则为 900的主要内容,如果未能解决你的问题,请参考以下文章

Haskell中是否有“继续”?

在python中将长数字格式化为字符串

数字格式化 把“1”格式化为“001”或“001”转换为1

谷歌表格将数字格式化为十亿/百万/数千,巧妙地[重复]

在R中将数字1000格式化为1k,将1000000格式化为1m等[重复]

获取java中矩阵中连续出现k次的所有数字