Converting big numbers to bigger factors in JavaScript - javascript

I have counter and sometimes it can get very big number, so I need to convert numbers like:
1300 => 1.3K
1000000 => 1M
And so on. How is this possible in JavaScript?

// Truncate a number to ind decimal places
function truncNb(Nb, ind) {
var _nb = Nb * (Math.pow(10,ind));
_nb = Math.floor(_nb);
_nb = _nb / (Math.pow(10,ind));
return _nb;
}
// convert a big number to k,M,G
function int2roundKMG(val) {
var _str = "";
if (val >= 1e9) { _str = truncNb((val/1e9), 1) + ' G';
} else if (val >= 1e6) { _str = truncNb((val/1e6), 1) + ' M';
} else if (val >= 1e3) { _str = truncNb((val/1e3), 1) + ' k';
} else { _str = parseInt(val);
}
return _str;
}

I picked up a nifty bit of code when looking for something to abbreviate and label byte sizes (e.g. 1024 bytes -> "1 KB") and changed it just a bit to suit your needs (1000 -> "1 K").
function abbreviate_number(num) {
var sizes = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
if (num < 1000) return num;
var i = parseInt(Math.floor(Math.log(num) / Math.log(1000)));
return ((i == 0) ? (num / Math.pow(1000, i)) : (num / Math.pow(1000, i)).toFixed(1)) + ' ' + sizes[i]; // use .round() in place of .toFixed if you don't want the decimal
};
Just for reference, here's what I needed.
function format_bytes(bytes) {
var sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
if (bytes == 0) return '';
if (bytes == 1) return '1 Byte';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return ((i == 0)? (bytes / Math.pow(1024, i)) : (bytes / Math.pow(1024, i)).toFixed(1)) + ' ' + sizes[i];
};

Pseudocode:
factor = 0;
while (value > 1000) {
value = value/1000;
factor++;
}
output value (you might perhaps limit output to 3 decimal places)
convert factor to unit and output (0 = none, 1 = K, 2 = M, 3 = G...)

You could just use a classic cascading number formatter of sorts
function format_num(num) {
if( num < 1000 )
return num;
else if( num < 1000000 )
return parseInt(num / 1000) + "K";
else if( num < 1000000000 )
return parseInt(num / 1000000) + "M";
//....
}
You just have to take care of rounding appropriately.

I came up to these answers late when I was looking for a clean way to do it but just in case if anyone was looking for copy pasting an angular filter doing that here is mine. same logic as above responses:)
just to make you sure for 001234 it returns 1k
html:
<div ng-repeat="d in data>
<div class="numbers">{{d | KGMPformat}}</div>
</div>
js:
// controller:
$scope.data = [123,12345,1234567,12345678,12345678901]
// filter:
(function(app) {
app.filter('KGMPformat', function() {
return function(value) {
if (value<1e3) return value;
if (value<1e6) return (value - value%1e3)/1e3 + "K";
if (value<1e9) return (value - value%1e6)/1e6 + "G";
if (value<1e12) return (value - value%1e9)/1e9 + "M";
if (value<1e15) return (value - value%1e12)/1e12 + "P";
return value;
};
});
})(myApp);

Related

How to return a string of a number with 1 decimal and others without the decimal place?

In JS, I want to output a string with 1 decimal place for particular values whilst others will be whole numbers (e.g. 999999 = "999.9k", 500000 = "500k" and 1000000 = 1M). Instead, I'm getting: 999999 = "1000.0k", 500000 = "500.0k" and 1000000 = 1.0M
This is what I've tried:
function formatLargeNumber(n) {
let s = "";
if (n < 1000) {
s += n;
} else if (n >= 1000 && n < 1000000) {
s += (Math.round(n)/1000).toFixed(1) + "k"
} else if (n >= 1000000) {
s += (Math.round(n)/1000000).toFixed(1) + "M"
}
return s
};
I've attempted to use Math.trunc but it outputs values such 499999 to equal 499.999k
I could convert the result to string first, split it by '.' character and add some if else statement whether or not I want to display the decimal place but I'm unsure how to write this out.
Here is something I found in https://www.codexworld.com/how-to/convert-file-size-bytes-kb-mb-gb-javascript/
// from https://www.codexworld.com/how-to/convert-file-size-bytes-kb-mb-gb-javascript/
function formatFileSize(bytes,decimalPoint) {
if(bytes == 0) return '0 Bytes';
var k = 1000,
dm = decimalPoint || 2,
sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
[123,3347,2234556,12345342355,123423444332,234.5678e15].forEach(n=>console.log(formatFileSize(n,1)))
A customised version of the script that will truncate the decimal digits (instead of rounding the number) after a given length could look like this:
// from https://www.codexworld.com/how-to/convert-file-size-bytes-kb-mb-gb-javascript/
function formatFileSize(bytes,decimalPoint) {
if(bytes == 0) return '0 Bytes';
var k = 1000,
dm = decimalPoint || 2,
sizes = ['', ' k', ' m', ' g', ' t', ' p', ' e', ' z', ' y'],
i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i))).toFixed(8).slice(0,dm-8).replace(/\.0*$/,"") + sizes[i];
}
[123,3347,2234556,12993453455,123063444332,234.5678e15].forEach(n=>console.log(formatFileSize(n,1)))
Having utilised the above mentioned solution to produce a snippet satisfying OP' s requirements I would like to point out that the way it calculates the quantities is not compliant to the actual definition of storage size units (see here). The factor between the units should actually be 1024 (2^10) instead of 1000 (10^3).

Advanced number formatting with incrementing suffix- javascript

I need some help with my function. I am new to coding and this task is part of Coderslang apprentice level tasks.
Implement a function that If n < 1000, it should be rounded to a single digit after a decimal point Else, to cut down the length of a number, we need to use letters 'K', 'M', 'B', 'T' to represent thousands, millions, billions or trillions. We're not really interested in being super precise here. If the number exceeds 999.99T it becomes 1.00aa, after 999.99aa goes 1.00ab.
When the number gets as high as 999.99az it will next turn into 1.00ba and so on.
The bold text is where I am having an issue, I am not sure how best to write this function and need help. Below is what I have tried so far but I am failing two parts of the test- The function formatNumber should work properly for numbers less than 999az. And the function formatNumber should not cut trailing zeros.
My code so far:
export const formatNumber = (n) => {
let number = n;
let suffix = [97, 92];
let newNumber = "";
if (n < 1000) {
return n.toFixed(1);
} else if (n < 1000000) {
return (n / 1000).toFixed(2) + 'K';
} else if (n < 1000000000) {
return (n / 1000000).toFixed(2) + 'M';
} else if (n < 1000000000000) {
return (n / 1000000000).toFixed(2) + 'B';
} else if (n < 1000000000000000){
return (n / 1000000000000).toFixed(2) + 'T';
}
while (number > 1000) {
(number /= 1000);
if (suffix[1] < 122) {
suffix[1]++;
} else {
suffix[0]++;
suffix[1] = 97
}
}
const stringNumber = String(number);
const i = stringNumber.indexOf(".");
if (i >= 0) {
newNumber = stringNumber.substring(0, i) + "." + stringNumber.substring(i + 1, i + 3);
} else {
newNumber = stringNumber + ".00";
}
return newNumber + String.fromCharCode(suffix[0]) + String.fromCharCode(suffix[1]);
}
I have searched this forum and others and am struggling, any help would be appreciated. I feel that either I am over complicating the thought process or I'm missing something obvious. Is it my while loop? I have tried number.toFixed and number.toExponential without luck
It was a very simple fix, I was over complicating this.
export const formatNumber = (n) => {
let number = n;
let suffix = [97, 92];
let newNumber = "";
if (n < 1000) {
return n.toFixed(1);
} else if (n < 1000000) {
return (n / 1000).toFixed(2) + 'K';
} else if (n < 1000000000) {
return (n / 1000000).toFixed(2) + 'M';
} else if (n < 1000000000000) {
return (n / 1000000000).toFixed(2) + 'B';
} else if (n < 1000000000000000){
return (n / 1000000000000).toFixed(2) + 'T';
}
while (number > 1000) {
(number /= 1000);
if (suffix[1] < 122) {
suffix[1]++;
} else {
suffix[0]++;
suffix[1] = 97
}
}
newNumber = number.toFixed(2);
return newNumber + String.fromCharCode(suffix[0]) + String.fromCharCode(suffix[1]);
}```

How to get String output as in single quote in javascript

Advance thanks, Question looks like simple but i could not able to find the solution.
function sumStrings(a, b)
{
return +a + +b;
}
sumStrings('1','2') //=>3
Expected output
sumStrings('1','2') // => '3'
After addition, add ' to beginning and end.
function sumStrings(a, b){
return "'" + (Number(a) + Number(b)) + "'";
}
console.log(sumStrings('1','2'));
function sumStrings(a, b) {
// Separate decimal part here
var pointa = a.indexOf(".");
var pointb = b.indexOf(".");
var deca = pointa != -1 ? a.substring(pointa + 1) : "0";
var decb = pointb != -1 ? b.substring(pointb + 1) : "0";
if (deca.length < decb.length)
deca += (Math.pow(10, decb.length - deca.length)).toString().substring(1);
else
decb += (Math.pow(10, deca.length - decb.length)).toString().substring(1);
var inta = pointa != -1 ? a.substring(0, pointa) : a;
var intb = pointb != -1 ? b.substring(0, pointb) : b;
// console.log(deca + " " + decb);
var decc = addBigInt(deca, decb);
var intc = addBigInt(inta, intb);
if (decc.length > deca.length) {
intc = addBigInt(intc, "1");
decc = decc.substring(1);
}
var lastZero = decc.length - 1;
while (lastZero >= 0 && decc[lastZero] == "0") {
lastZero--;
}
if (lastZero >= 0)
return intc + "." + decc.substring(0, lastZero + 1);
else
return intc;
}
function addBigInt(a, b) {
var inda = a.length - 1;
var indb = b.length - 1;
var c = [];
const zero = "0".charCodeAt(0);
var carry = 0;
var sum = 0;
while (inda >= 0 && indb >= 0) {
var d1 = a.charCodeAt(inda--) - zero;
var d2 = b.charCodeAt(indb--) - zero;
sum = (d1 + d2 + carry);
carry = Math.floor(sum / 10);
sum %= 10;
c.unshift(sum);
}
if (inda >= 0) {
while (carry && inda >= 0) {
sum = a.charCodeAt(inda--) - zero + carry;
c.unshift(sum % 10);
carry = Math.floor(sum / 10);
}
c.unshift(a.substring(0, inda + !carry));
} else {
while (carry && indb >= 0) {
sum = b.charCodeAt(indb--) - zero + carry;
c.unshift(sum % 10);
carry = Math.floor(sum / 10);
}
c.unshift(b.substring(0, indb + !carry));
}
if (carry)
c.unshift(carry);
return c.join("");
}
console.log(sumStrings("1","2"));
console.log(sumStrings("800","9567"));
console.log(sumStrings("99.1","1"));
console.log(sumStrings("00103","08567"));
console.log(sumStrings("50095301248058391139327916261.5","81055900096023504197206408605"));
If you want to escape the single quote, you can try to add a backslash before the single quote.
i.e.
var x = '\'5\'';
With the new template literal you can try this:
a=`'5'`;
console.log(a);

How to create custom function in javascript that looks like a dot notation? e.g., str.getFirstIndex();

I was looking on the code on our team project, and was wondering if I can make it better, "clean and easy to understand".
I've done a research but I couldn't found any, maybe Its because I don't know the terminologies use?
Anyway here is the code:
var num = 10000;
function toShortMoney(num) {
var thousand = Math.pow(10, 3),
million = Math.pow(10, 6),
billion = Math.pow(10, 9),
negative = false,
money = '0',
str = '';
str = num.toString();
if(str.indexOf('-') > -1) {
negative = true;
str = str.slice(1);
num = str.valueOf(str);
}
if(num < million && num >= thousand) { //thousand
num = (Math.floor(num / thousand)).toFixed(0);
money = num + 'K';
}
else if(num < billion && num >= million) { //million
num = (num / million).toFixed(2).replace(/(\.?0+$)/,'');
money = num + 'M';
}
else {
money = Math.floor(num).toFixed(0);
}
if(negative)
return '($' + money + ')';
return '$' + money;
}
Initially I can access toShortMoney by putting the variable num as a parameter,
but How could I access toShortMoney by doing a dot notation like function?
e.g., num.toShortMoney(); //returns $10k
If you want this method to be available on any number object, you'll have to add the method to Number's prototype.
Number.prototype.toShortMoney = function() {
// in the context of being called on a number, the number will
// not be an argument, but you access it via this eg.:
return '$' + this;
};
However, some people feel like adding methods to the prototypes of the native classes is bad practice (except for polyfilling).. But I would say mostly that's true for library projects.
Good luck
You can adjust num to this within toShortMoney, you can also extend String.prototype to accept wither Number or String
function toShortMoney() {
var thousand = Math.pow(10, 3),
million = Math.pow(10, 6),
billion = Math.pow(10, 9),
negative = false,
money = '0',
str = '';
num = this;
str = num.toString();
if(str.indexOf('-') > -1) {
negative = true;
str = str.slice(1);
num = str.valueOf(str);
}
if(num < million && num >= thousand) { //thousand
num = (Math.floor(num / thousand)).toFixed(0);
money = num + 'K';
}
else if(num < billion && num >= million) { //million
num = (num / million).toFixed(2).replace(/(\.?0+$)/,'');
money = num + 'M';
}
else {
money = Math.floor(num).toFixed(0);
}
if(negative)
return '($' + money + ')';
return '$' + money;
}
String.prototype.toShortMoney = Number.prototype.toShortMoney = toShortMoney

Convert long number into abbreviated string in JavaScript, with a special shortness requirement

In JavaScript, how would one write a function that converts a given [edit: positive integer] number (below 100 billion) into a 3-letter abbreviation -- where 0-9 and a-z/A-Z are counting as a letter, but the dot (as it's so tiny in many proportional fonts) would not, and would be ignored in terms of the letter limit?
This question is related to this helpful thread, but it's not the same; for instance, where that function would turn e.g. "123456 -> 1.23k" ("123.5k" being 5 letters) I am looking for something that does "123456 -> 0.1m" ("0[.]1m" being 3 letters). For instance, this would be the output of hoped function (left original, right ideal return value):
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"
Thanks!
Update: Thanks! An answer is in and works per the requirements when the following amendments are made:
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;
}
Approach 1: Built-in library
I would recommend using Javascript's built-in library method Intl.NumberFormat
Intl.NumberFormat('en-US', {
notation: "compact",
maximumFractionDigits: 1
}).format(2500);
Approach 2: No library
But you can also create these abbreviations with simple if statements, and without the complexity of Math, maps, regex, for-loops, etc.
Formatting Cash value with K
const formatCash = n => {
if (n < 1e3) return n;
if (n >= 1e3) return +(n / 1e3).toFixed(1) + "K";
};
console.log(formatCash(2500));
Formatting Cash value with 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));
Using negative numbers
let format;
const number = -1235000;
if (number < 0) {
format = '-' + formatCash(-1 * number);
} else {
format = formatCash(number);
}
I believe ninjagecko's solution doesn't quite conform with the standard you wanted. The following function does:
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) {
shortValue = shortValue.toFixed(1);
}
return shortValue+suffixes[suffixNum];
}
For values greater than 99 trillion no letter will be added, which can be easily fixed by appending to the 'suffixes' array.
Edit by Philipp follows: With the following changes it fits with all requirements perfectly!
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;
}
This handles very large values as well and is a bit more succinct and efficient.
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;
}
Results:
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
The modern, easy, built-in, highly customizable, and 'no-code' way: Intl.FormatNumber 's format function (compatibility graph)
var numbers = [98721, 9812730,37462,29,093484620123, 9732,0283737718234712]
for(let num of numbers){
console.log(new Intl.NumberFormat( 'en-US', { maximumFractionDigits: 1,notation: "compact" , compactDisplay: "short" }).format(num));
}
98.7K
9.8M
37.5K
29
93.5B
9.7K
283.7T
Notes:
If you're using typescript add a //#ts-ignore before notation (source)
And a list of all the keys in the options parameter: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#parameters
When using style: 'currency', you must remove maximumFractionDigits, as it will figure this out for you.
Here's what I think is a fairly elegant solution. It does not attempt to deal with negative numbers:
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;
}
Examples:
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'
I think you cant try this numeraljs/
If you want convert 1000 to 1k
console.log(numeral(1000).format('0a'));
and if you want convert 123400 to 123.4k try this
console.log(numeral(123400).format('0.0a'));
Based on my answer at https://stackoverflow.com/a/10600491/711085 , your answer is actually slightly shorter to implement, by using .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;
}
}
(As usual, don't use Math unless you know exactly what you're doing; assigning var pow=... and the like would cause insane bugs. See link for a safer way to do this.)
> 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"
You will need to catch the case where the result is >=1 trillion, if your requirement for 3 chars is strict, else you risk creating corrupt data, which would be very bad.
Code
const SI_PREFIXES = [
{ 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 abbreviateNumber = (number) => {
if (number === 0) return number
const tier = SI_PREFIXES.filter((n) => number >= n.value).pop()
const numberFixed = (number / tier.value).toFixed(1)
return `${numberFixed}${tier.symbol}`
}
abbreviateNumber(2000) // "2.0k"
abbreviateNumber(2500) // "2.5k"
abbreviateNumber(255555555) // "255.6M"
Test:
import abbreviateNumber from './abbreviate-number'
test('abbreviateNumber', () => {
expect(abbreviateNumber(0)).toBe('0')
expect(abbreviateNumber(100)).toBe('100')
expect(abbreviateNumber(999)).toBe('999')
expect(abbreviateNumber(1000)).toBe('1.0k')
expect(abbreviateNumber(100000)).toBe('100.0k')
expect(abbreviateNumber(1000000)).toBe('1.0M')
expect(abbreviateNumber(1e6)).toBe('1.0M')
expect(abbreviateNumber(1e10)).toBe('10.0G')
expect(abbreviateNumber(1e13)).toBe('10.0T')
expect(abbreviateNumber(1e16)).toBe('10.0P')
expect(abbreviateNumber(1e19)).toBe('10.0E')
expect(abbreviateNumber(1500)).toBe('1.5k')
expect(abbreviateNumber(1555)).toBe('1.6k')
expect(abbreviateNumber(undefined)).toBe('0')
expect(abbreviateNumber(null)).toBe(null)
expect(abbreviateNumber('100')).toBe('100')
expect(abbreviateNumber('1000')).toBe('1.0k')
})
Here's another take on it. I wanted 123456 to be 123.4K instead of 0.1M
UPDATE 2022, Dec. 5
Added support for negative values and non-integer values
function convert(value) {
var length = (Math.abs(parseInt(value, 10)) + '').length,
index = Math.ceil((length - 3) / 3),
suffix = ['K', 'M', 'B', 'T'];
if (length < 4) return value;
return (value / Math.pow(1000, index))
.toFixed(1)
.replace(/\.0$/, '') + suffix[index - 1];
}
var tests = [1234, 7890, -990123467, 123456, 750000.1234, 567890, 800001, 2000000, 20000000, 201234567, 801234567, 1201234567];
for (var i in tests)
document.writeln('<p>convert(' + tests[i] + ') = ' + convert(tests[i]) + '</p>');
After some playing around, this approach seems to meet the required criteria. Takes some inspiration from #chuckator's answer.
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 is the Javascript standard 'package' for implemented internationalized behaviours. Intl.NumberFormatter is specifically the localized number formatter. So this code actually respects your locally configured thousands and decimal separators.
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) // Gives 999B
Related question: Abbreviate a localized number in JavaScript for thousands (1k) and millions (1m)
I'm using this function to get these values.
function Converter(number, fraction) {
let ranges = [
{ divider: 1, suffix: '' },
{ divider: 1e3, suffix: 'K' },
{ divider: 1e6, suffix: 'M' },
{ divider: 1e9, suffix: 'G' },
{ divider: 1e12, suffix: 'T' },
{ divider: 1e15, suffix: 'P' },
{ divider: 1e18, suffix: 'E' },
]
//find index based on number of zeros
let index = (Math.abs(number).toString().length / 3).toFixed(0)
return (number / ranges[index].divider).toFixed(fraction) + ranges[index].suffix
}
Each 3 digits has different suffix, that's what i'm trying to find firstly.
So, remove negative symbol if exists, then find how many 3 digits in this number.
after that find appropriate suffix based on previous calculation added to divided number.
Converter(1500, 1)
Will return:
1.5K
Use as a Number Prototype
For easy and direct you. Simply make a prototype of it. Here is an example.
Number.prototype.abbr = function (decimal = 2): string {
const notations = ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'],
i = Math.floor(Math.log(this) / Math.log(1000));
return `${parseFloat((this / Math.pow(1000, i)).toFixed(decimal))}${notations[i]}`;
};
Indian Currency format to (K, L, C) Thousand, Lakh, Crore
const formatCash = n => {
if (n < 1e3) return n;
if (n >= 1e3 && n < 1e5) return +(n / 1e3).toFixed(1) + "K";
if (n >= 1e5 && n <= 1e6) return +(n / 1e5).toFixed(1) + "L";
if (n >= 1e6 && n <= 1e9) return +(n / 1e7).toFixed(1) + "C";
};
Try it :
const unitlist = ['', 'K', 'M', 'B']
export function AmountConveter (number: number) {
const sign = Math.sign(number)
let unit = 0
while (Math.abs(number) > 1000) {
unit = unit + 1
number = Math.floor(Math.abs(number) / 100) / 10
}
return sign * Math.abs(number) + unitlist[unit]
}
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));
}
alert(converse_number(100000000000));
#nimesaram
Your solution will not be desirable for the following case:
Input 50000
Output 50.0k
Following solution will work fine.
const convertNumberToShortString = (
number: number,
fraction: number
) => {
let newValue: string = number.toString();
if (number >= 1000) {
const ranges = [
{ divider: 1, suffix: '' },
{ divider: 1e3, suffix: 'k' },
{ divider: 1e6, suffix: 'm' },
{ divider: 1e9, suffix: 'b' },
{ divider: 1e12, suffix: 't' },
{ divider: 1e15, suffix: 'p' },
{ divider: 1e18, suffix: 'e' }
];
//find index based on number of zeros
const index = Math.floor(Math.abs(number).toString().length / 3);
let numString = (number / ranges[index].divider).toFixed(fraction);
numString =
parseInt(numString.substring(numString.indexOf('.') + 1)) === 0
? Math.floor(number / ranges[index].divider).toString()
: numString;
newValue = numString + ranges[index].suffix;
}
return newValue;
};
// Input 50000
// Output 50k
// Input 4500
// Output 4.5k
Even more Abbreviation?
Let's make "Qa" as Quadrillions and "Qi" as Quintillions... maybe "Sx" Sextillions, and So on...
if (num >= 1e3 !& num >= 1e6) {num2 = num/1e3 + "K";};
if (num >= 1e6 !& num >= 1e9) {num2 = num/1e6 + "M";};
if (num >= 1e9 !& num >= 1e12) {num2 = num/1e9 + "B";};
if (num >= 1e12 !& num >= 1e15) {num2 = num/1e12 + "T";};
if (num >= 1e15 !& num >= 1e18) {num2 = num/1e15 + "Qa";};
if (num >= 1e18 !& num >= 1e21) {num2 = num/1e18 + "Qi";};
if (num >= 1e21 !& num >= 1e24) {num2 = num/1e21 + "Sx";};
if (num >= 1e24 !& num >= 1e27) {num2 = num/1e24 + "Sp";};
if (num >= 1e27 !& num >= 1e30) {num2 = num/1e27 + "Oc";};
if (num >= 1e30 !& num >= 1e93) {num2 = num/1e30 + "No";};
if (num >= 1e33 !& num >= 1e36) {num2 = num/1e33 + "Dc";};
if (num >= 1e36 !& num >= 1e39) {num2 = num/1e36 + "UDc";};
if (num >= 1e39) {num2 = num/1e39 + "DDc";};
Pure Javascript
n --> 292234567890 to 292,234,567,890
s --> 292,234,567,890 to 292,234,567,890 + K | M | B | T | q | Q | s | S | o | n | d | U
s --> 292,234,567,890B to 292.2B
return --> Remove 4th digit 292.2B to 292B
function format(n) {n=n.toLocaleString();
let s = n+('KMBTqQsSondU'.split('')[n.split(',').length-2]||'')
s = s.replace(/,([1-9])[\d,.]+|,[\d,.]+/g,(m,a)=>a?'.'+a:'')
return s.replace(/(\d{3})\.\d/, '$1');
}
//Just for show
let negative = [-1991078910902345678907890, -991708910902345678907890,-10902345678907890, -1000234567890, -1234567890, -12345678, -1234567, -12345, -1234, -123, -12, -1, 0]
let positive = [1991078910902345678907890, 991078910902345678907890,10902345678907890, 1000234567890, 1234567890, 12345678, 1234567, 12345, 1234, 123, 12, 1, 0]
let table = '<table cellspacing="0"><tbody>';
negative.forEach(function(x){ table += '<tr><td style="padding-right: 30px;">'+x+'</td><td>'+ format(x)+'</td></tr>'})
table +='</tbody></table><table cellspacing="0"><tbody>'
positive.forEach(function(x){ table += '<tr><td style="padding-right: 30px;">'+x+'</td><td>'+ format(x)+'</td></tr>'})
document.body.innerHTML = table+'</tbody></table>';
tr:nth-child(odd) {background: #f8f8f8;}
td {padding: 5px 10px;}
table {
font-size: 13px;
display: inline-table;
padding-right: 30px;
}
Pure Javascript
Pros: Native Built in Solution
Cons: Maxes out at Trillion
function format(x) {let o={maximumFractionDigits: 1,notation: "compact",compactDisplay: "short"};
let a=x<0,n=x*Math.sign(x);s=new Intl.NumberFormat('en-US', o).format(n);return a?'-'+s:s;
}
//Just for show
let negative = [-1991078910902345678907890, -991078910902345678907890,-10902345678907890, -1000234567890, -1234567890, -12345678, -1234567, -12345, -1234, -123, -12, -1, 0]
let positive = [1991078910902345678907890, 991078910902345678907890,10902345678907890, 1000234567890, 1234567890, 12345678, 1234567, 12345, 1234, 123, 12, 1, 0]
let table = '<table cellspacing="0"><tbody>';
negative.forEach(function(x){ table += '<tr><td style="padding-right: 10px;">'+x+'</td><td>'+ format(x)+'</td></tr>'})
table +='</tbody></table><table cellspacing="0"><tbody>'
positive.forEach(function(x){ table += '<tr><td style="padding-right: 10px;">'+x+'</td><td>'+ format(x)+'</td></tr>'})
document.body.innerHTML = table+'</tbody></table>';
tr:nth-child(odd) {background: #f8f8f8;}
td {padding: 5px 10px;}
table {
font-size: 12px;
display: inline-table;
padding-right: 10px;
}

Categories

Resources