在JavaScript中将长数字转换为缩写string,并具有特殊的简短要求

在JavaScript中,如何编写一个将给定[编辑: 正整数 ]数字(低于1000亿)转换为3个字母的缩写的函数 – 其中0-9和az / AZ计数为字母, (因为它在许多比例字体中很小)不会,并且在字母限制方面将被忽略?

这个问题与这个有用的线程有关 ,但不一样; 例如,那个函数会变成例如“123456 – > 1.23k”(123.5k是5个字母),我正在寻找“123456 – > 0.1m”(“0 [。] 1m”是3个字母)。 例如,这将是希望函数的输出(左原,理想的返回值):

0 "0" 12 "12" 123 "123" 1234 "1.2k" 12345 "12k" 123456 "0.1m" 1234567 "1.2m" 12345678 "12m" 123456789 "0.1b" 1234567899 "1.2b" 12345678999 "12b" 

谢谢!

更新:谢谢! 在做出以下修改时,答案已经符合要求:

 function abbreviateNumber(value) { var newValue = value; if (value >= 1000) { var suffixes = ["", "k", "m", "b","t"]; var suffixNum = Math.floor( (""+value).length/3 ); var shortValue = ''; for (var precision = 2; precision >= 1; precision--) { shortValue = parseFloat( (suffixNum != 0 ? (value / Math.pow(1000,suffixNum) ) : value).toPrecision(precision)); var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g,''); if (dotLessShortValue.length <= 2) { break; } } if (shortValue % 1 != 0) shortNum = shortValue.toFixed(1); newValue = shortValue+suffixes[suffixNum]; } return newValue; } 

我相信ninjagecko的解决scheme不太符合你想要的标准。 以下function确实:

 function intToString (value) { var suffixes = ["", "k", "m", "b","t"]; var suffixNum = Math.floor((""+value).length/3); var shortValue = parseFloat((suffixNum != 0 ? (value / Math.pow(1000,suffixNum)) : value).toPrecision(2)); if (shortValue % 1 != 0) { var shortNum = shortValue.toFixed(1); } return shortValue+suffixes[suffixNum]; } 

对于超过99兆的值,不会添加任何字母,可以通过附加到“后缀”数组来轻松修复。

由Philipp编辑如下:通过以下更改,完全符合所有要求!

 function abbreviateNumber(value) { var newValue = value; if (value >= 1000) { var suffixes = ["", "k", "m", "b","t"]; var suffixNum = Math.floor( (""+value).length/3 ); var shortValue = ''; for (var precision = 2; precision >= 1; precision--) { shortValue = parseFloat( (suffixNum != 0 ? (value / Math.pow(1000,suffixNum) ) : value).toPrecision(precision)); var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g,''); if (dotLessShortValue.length <= 2) { break; } } if (shortValue % 1 != 0) shortNum = shortValue.toFixed(1); newValue = shortValue+suffixes[suffixNum]; } return newValue; } 

这也处理了非常大的值,并且更加简洁和高效。

 abbreviate_number = function(num, fixed) { if (num === null) { return null; } // terminate early if (num === 0) { return '0'; } // terminate early fixed = (!fixed || fixed < 0) ? 0 : fixed; // number of decimal places to show var b = (num).toPrecision(2).split("e"), // get power k = b.length === 1 ? 0 : Math.floor(Math.min(b[1].slice(1), 14) / 3), // floor at decimals, ceiling at trillions c = k < 1 ? num.toFixed(0 + fixed) : (num / Math.pow(10, k * 3) ).toFixed(1 + fixed), // divide by power d = c < 0 ? c : Math.abs(c), // enforce -0 is 0 e = d + ['', 'K', 'M', 'B', 'T'][k]; // append power return e; } 

结果:

 for(var a='', i=0; i < 14; i++){ a += i; console.log(a, abbreviate_number(parseInt(a),0)); console.log(-a, abbreviate_number(parseInt(-a),0)); } 0 0 -0 0 01 1 -1 -1 012 12 -12 -12 0123 123 -123 -123 01234 1.2K -1234 -1.2K 012345 12.3K -12345 -12.3K 0123456 123.5K -123456 -123.5K 01234567 1.2M -1234567 -1.2M 012345678 12.3M -12345678 -12.3M 0123456789 123.5M -123456789 -123.5M 012345678910 12.3B -12345678910 -12.3B 01234567891011 1.2T -1234567891011 -1.2T 0123456789101112 123.5T -123456789101112 -123.5T 012345678910111213 12345.7T -12345678910111212 -12345.7T 

我想你不能尝试这个numbersjs /

如果你想转换1000到1K

 console.log(numeral(1000).format('0a')); 

如果你想转换123400到123.4K试试这个

 console.log(numeral(123400).format('0.0a')); 

基于我的回答在https://stackoverflow.com/a/10600491/711085 ,您的答案实际上稍短,通过使用.substring(0,3)

 function format(n) { with (Math) { var base = floor(log(abs(n))/log(1000)); var suffix = 'kmb'[base-1]; return suffix ? String(n/pow(1000,base)).substring(0,3)+suffix : ''+n; } } 

(像往常一样,除非你确切地知道你在做什么,否则不要使用Math;分配var pow=...等等会引起疯狂的错误,请参阅链接以获得更安全的方法。

 > tests = [-1001, -1, 0, 1, 2.5, 999, 1234, 1234.5, 1000001, Math.pow(10,9), Math.pow(10,12)] > tests.forEach(function(x){ console.log(x,format(x)) }) -1001 "-1.k" -1 "-1" 0 "0" 1 "1" 2.5 "2.5" 999 "999" 1234 "1.2k" 1234.5 "1.2k" 1000001 "1.0m" 1000000000 "1b" 1000000000000 "1000000000000" 

如果您对3个字符的要求是严格的,您需要了解结果大于或等于1万亿的情况,否则您将冒险创build损坏的数据,这将会非常糟糕。

经过一番玩,这种方法似乎符合所需的标准。 从@ chuckator的回答中得到一些启发。

 function abbreviateNumber(value) { if (value <= 1000) { return value.toString(); } const numDigits = (""+value).length; const suffixIndex = Math.floor(numDigits / 3); const normalisedValue = value / Math.pow(1000, suffixIndex); let precision = 2; if (normalisedValue < 1) { precision = 1; } const suffixes = ["", "k", "m", "b","t"]; return normalisedValue.toPrecision(precision) + suffixes[suffixIndex]; } 

Intl是实现国际化行为的Javascript标准“包”。 Intl.NumberFormatter特别是本地化的数字格式化程序。 所以这个代码实际上尊重你的本地configuration数千和十进制分隔符。

 intlFormat(num) { return new Intl.NumberFormat().format(Math.round(num*10)/10); } abbreviateNumber(value) { let num = Math.floor(value); if(num >= 1000000000) return this.intlFormat(num/1000000000)+'B'; if(num >= 1000000) return this.intlFormat(num/1000000)+'M'; if(num >= 1000) return this.intlFormat(num/1000)+'k'; return this.intlFormat(num); } 

abbreviateNumber(999999999999)//给999B

相关问题: 缩短数以千计(1k)和数百万(1m)

这是我认为是一个相当优雅的解决scheme。 它不会试图处理负数

 const COUNT_ABBRS = [ '', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' ]; function formatCount(count, withAbbr = false, decimals = 2) { const i = 0 === count ? count : Math.floor(Math.log(count) / Math.log(1000)); let result = parseFloat((count / Math.pow(1000, i)).toFixed(decimals)); if(withAbbr) { result += `${COUNT_ABBRS[i]}`; } return result; } 

例如

  formatCount(1000, true); => '1k' formatCount(100, true); => '100' formatCount(10000, true); => '10k' formatCount(10241, true); => '10.24k' formatCount(10241, true, 0); => '10k' formatCount(10241, true, 1) => '10.2k' formatCount(1024111, true, 1) => '1M' formatCount(1024111, true, 2) => '1.02M' 

我在这里find了更好的解决scheme, 用小提琴运行的例子 ,在许多情况下@chucktator解决scheme返回NaN。 它对我来说工作得很好。

  function converse_number (labelValue) { // Nine Zeroes for Billions return Math.abs(Number(labelValue)) >= 1.0e+9 ? Math.abs(Number(labelValue)) / 1.0e+9 + "B" // Six Zeroes for Millions : Math.abs(Number(labelValue)) >= 1.0e+6 ? Math.abs(Number(labelValue)) / 1.0e+6 + "M" // Three Zeroes for Thousands : Math.abs(Number(labelValue)) >= 1.0e+3 ? Math.abs(Number(labelValue)) / 1.0e+3 + "K" : Math.abs(Number(labelValue)); } 

警报(converse_number(千亿));

我相信在接受的例子中有一个错误。 包含未使用的var shortNum的函数末尾的注意行应该是shortValue

 function abbreviateNumber (value) { var newValue = value if (value >= 1000) { var suffixes = ['', 'k', 'm', 'b', 't'] var suffixNum = Math.floor(('' + value).length / 3) var shortValue = '' for (var precision = 2; precision >= 1; precision--) { shortValue = parseFloat((suffixNum !== 0 ? (value / Math.pow(1000, suffixNum)) : value).toPrecision(precision)) var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g, '') if (dotLessShortValue.length <= 2) { break } } if (shortValue % 1 !== 0) shortValue = shortValue.toFixed(1) newValue = shortValue + suffixes[suffixNum] } return newValue }