How to format numeric values with pattern? - javascript

I'm finding an equivalent to Java's DecimalFormat in JavaScript. I would like to format given numeric values with given decimal pattern like
"#,###.00"
"###.##"
"#,###.##"
"$#,##0.00"
"###,###.00"
"$###,###.00"
"###,###.###"
"####,####.000"
Has there any way to achieve it?

Part 1 - formatting
I would recommend using the Intl.NumberFormat natively supported in javascript, although it may not be supported by older browsers. Looks like IE11 has it, but not android.
So if you wanted to support US Dollars you would simply use something like this
var dollarFormat = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' });
var amountInDollars = dollarFormat.format(123456.123);
// amountInDollars = "$123,456.12"
But this also rounds up for you, for example
var roundedDollars = dollarFormat.format(555.555);
// roundedDollars = "$555.56";
For the numeric cases just use a different formatter. The default 'en-US' adds commas, a decimal before fractional numbers, and limits to 3 fractional numbers. But this is configurable.
var numberFormat = new Intl.NumberFormat('en-US');
var formatted = numberFormat.format(123456.123456);
// formatted = "123,456.123"
var numberFormat2decimals = new Intl.NumberFormat('en-US', { maximumFractionDigits: 2 });
var formatted2 = numberFormat2decimals.format(123456.123456);
// formatted2 = "123,456.12"
You can set maximum and minimum for fraction, integer, and significant digits, and this also supports international formats. Since it's native javascript, I think it's a good way to go if your platforms support it.
MDN is an excellent reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat
Part 2 - the 0's
To achieve the 0's in your formats you'll have to modify the value before passing to the formatter. If you require a minimum fractional amount, you're fine for things like .00, the currency formatter will do that by default. If you've got fractal numbers you don't want, just use Math.trun() to truncate the values.
var num = Math.trun(1234.1234);
// num = 1234
Now to change something like 12345 to 12340 we'll have to remove some of the numeric value. We can find out much by converting to a string, pulling the last character, and converting back.
var num = 123456.12345;
var wholeNum = Math.trunc(num);
// wholeNum = 123456;
var toRemove = Number.parseInt(wholeNum.toString().slice(-1), 10);
// toRemove = 6
// slice(-1) gives us the right-most character of a string.
// Notice the ', 10' at the end, this is important to indicate which number base to use for parseInt.
var wholeNumEnding0 = wholeNum - toRemove;
// wholeNumEnding0 = 123450
Hopefully that's what you're looking to accomplish? I didn't perform any rounding here.

Note: I typed this at speed, excuse any mistakes, there might be better ways to do it too.
If you don't want to rely on a library, you could do something like the following:
var number = 100000.00000000000012422;
function FormatNumber(no){
no = no.toFixed(2);
no = no.toString().split('.');
var p1 = no[0];
p1 = p1.substring(0, p1.length - 3) + ',' + p1.substring(p1.length - 3);
no = p1 + '.' + no[1];
console.log(no);
}
FormatNumber(number);
The FormatNumber function takes a number as a parameter (you would probably want to expand that to include e.g. decimal places). It converts the number to the required decimal places, the turns it into a string and splits it by the decimal separator '.'.
The next step is to add a thousands separator three characters from the back, then it's just a matter of joining the remaining characters back together.
JSFiddle
If you wanted to get a ',' every 3 characters you could write a little more 'complex' formatter, something along the lines of the following:
no = no.toFixed(2);
no = no.toString().split('.');
var p1 = no[0];
var arr = [];
arr = p1.split("").reverse().join("").match(/[\s\S]{1,3}/g) || [];
arr = arr.reverse();
p1 = "";
for(var i = 0; i < arr.length; i++){
p1 += arr[i].split("").reverse().join("");
if(i != arr.length - 1){
p1 += ',';
}
}
no = p1 + '.' + no[1];
This method splits the number into an array by each number, reverses the array as we need to start from the end of the string to get accurate result.
Then we iterate the array of strings with 3 or less values by splitting the number into an array again, reversing it and joining back together and then appending to p1. If it's the last item, it doesn't add a comma.
Lastly we take the decimal and append to built string.
JSFiddle

Related

How to prevent very small numbers from being converted to scientific notation?

I have to use very small numbers:
var x = 0.00000006;
When I run console.log(x), it shows:
6e-8
I don't want it to show 6e-8 , I want it to show 0.00000006.
Later I need to plot it on a graph, so I can't convert it to a string.
How to keep it a small number without converting it to a string or scientific notation?
You can convert it to "fixed" shape and get it to look like you want. Example would be:
var number = 6e-8; //this is your number
number = number.toFixed(8) //but since you won't always know how many decimal points you have you can use something like
number = number.toFixed(number.toString().split('-')[1]); //where you split your number, see how many decimals it has and pass that number to .toFixed method
This will be more correct,
only the last part after the e- notation is not the enough to be always the number you need to provide in toFixed
// containing Scientific Notation to a readable number string
export const convertScientificNotationNumber = (value) => {
const decimalsPart = value?.toString()?.split('.')?.[1] || '';
const eDecimals = Number(decimalsPart?.split('e-')?.[1]) || 0;
const countOfDecimals = decimalsPart.length + eDecimals;
return Number(value).toFixed(countOfDecimals);
//0.4210854715202004e-14).toFixed(30)
};

Append extra zeroes to decimal to make 4.5 look 4.500 but 4.5234 should be 4.5234

I have a value fetched from the database, it's like:
4.5 which should be 4.500
0.01 which should be 0.010
11 which should be 11.000
so I used this piece of code
sprintf("%.3f",(double)$html['camp_cpc'])
But here arised another problem. If $html['camp_cpc'] = '4.5234', then also it displays 4.523 instead of original value 4.5234
Also for other values with larger decimal like 0.346513, its only showing up to 0.346.
How can I solve this problem in JavaScript also?
Floats 4.5 and 4.500 correspond to the same number, so they cannot (and should not) be used/stored in a way that preserves the different representation. If you need to preserve the original representation given by a user, you need to store this field as a list (string) and convert to a float whenever you need the float value
In Javascript at least, this is an implementation of what I think you want:
function getValue(x, points) {
var str = x.toString();
// Convert to string
var idx = str.indexOf(".");
// If the number is an integer
if(!~idx) return str + "." + "0".repeat(points);
// Get the tail of the number
var end = str.substr(idx+1);
// If the tail exceeds the number of decimal places, return the full string
if(end.length > points) return str;
// Otherwise return the int + the tail + required number of zeroes
return str.substr(0, idx) + "." + end.substr(0, points) + "0".repeat(points-end.length);
}
console.log(getValue(4.5, 3)); //4.500
console.log(getValue(0.01, 3)); //0.010
console.log(getValue(11, 3)); //11.000
Working demo (Makes use of ES6 String.repeat for demonstration purposes)
The important thing to note here is that this is string manipulation. Once you start to say "I want the number to look like..." it's no longer a number, it's what you want to show the user.
This takes your number, converts it to the string and pads the end of the string with the appropriate number of zeroes. If the decimal exceeds the number of places required the full number is returned.
In PHP, use %0.3f — and you don't need to cast as (double)
<?php
echo sprintf("%0.3f", 4.5); // "4.500"
echo sprintf("%0.3f", 4.5234); // "4.523"
If you want to display 4 decimal places, use %0.4f
echo sprintf("%0.4f", 4.5); // "4.5000"
echo sprintf("%0.4f", 4.5234); // "4.5234"
To do this in JavaScript
(4.5).toFixed(3); // "4.500"
It could look sth. like this:
var n = [4.5234, 0.5, 0.11, 456.45];
var temp_n;
for(var i = 0; i < n.length; i++) {
temp_n = String(n[i]).split(".");
if(temp_n[1] == null || temp_n[1].length < 3) {
n[i] = n[i].toFixed(3);
}
}

Creating a string of digits in javascript each within a limit

How can I use javascript to randomly create a 20 digit string of numbers, each of the digits ranging only between 1 and 5?
An example would be: 52431425331425141521
As well as the logical algorithm I gave in my comment above, you could just use this one-liner:
var result = Math.floor(Math.random()*95367431640625).toString(5)
.split("").map(function(n) {return +n+1;}).join("");
Essentially, pick a random integer between 0 and 520-1, convert it to base 5, then increment all the digits by one, so they're all between 1 and 5 ^_^
EDIT: Just realised this won't handle low numbers too well. Try this:
var result = (
new Array(20).join("0")
+
Math.floor(Math.random()*95367431640625).toString(5)
).slice(-20).split("").map(function(n) {return +n+1;}).join(""));
This does basically the same, except it prepends 19 zeroes to the front of your number, then slices off the last 20 characters. This will allow it to handle leading zeroes correctly to give a 20-digit number in all cases.
You can use this:
function random_string()
{
var text = "";
var string = "12345";
for( var i=0; i < 20; i++ )
text += string.charAt(Math.floor(Math.random() * string.length));
return text;
}
random_string();

using the digits of a number as an array

var number = 342345820139586830203845861938475676
var output = []
var sum = 0;
while (number) {
output.push(number % 10);
number = Math.floor(number/10);
}
output = output.reverse();
function addTerms () {
for (i = 0; i < output.length; i=i+2) {
var term = Math.pow(output[i], output[i+1]);
sum += term;
}
return sum;
}
document.write(output);
document.write("<br>");
document.write(addTerms());
I am trying to take that large number and split it into its digits. Then, find the sum of the the first digit raised to the power of the 2nd, 3rd digit raiseed to the 4th, 5th raised to the 6th and so on. for some reason, my array is returning weird digits, causing my sum to be off. the correct answer is 2517052. Thanks
You're running into precision issues within JavaScript. Just evaluate the current value of number before you start doing anything, and the results may surprise you:
>>> var number = 342345820139586830203845861938475676; number;
3.423458201395868e+35
See also: What is JavaScript's highest integer value that a Number can go to without losing precision?
To resolve your issue, I'd store your input number as an array (or maybe even a string), then pull the digits off of that.
This will solve your calculation with the expected result of 2517052:
var number = "342345820139586830203845861938475676";
var sum = 0;
for(var i=0; i<number.length; i=i+2){
sum += Math.pow(number.charAt(i), number.charAt(i+1));
}
sum;
JavaScript stores numbers in floating point format (commonly double). double can store precisely only 15 digits.
You can use string to store this large number.
As mentioned, this is a problem with numeric precision. It applies to all programming languages that use native numeric formats. Your problem works fine if you use a string instead
var number = '342345820139586830203845861938475676'
var digits = number.split('')
var total = 0
while (digits.length > 1) {
var [n, power] = digits.splice(0, 2)
total += Math.pow(n, power)
}
(the result is 2517052, byt the way!)
Cast the number as a string and then iterate through it doing your math.
var number = "342345820139586830203845861938475676";//number definition
var X = 0;//some iterator
var numberAtX = 0 + number.charAt(X);//number access
The greatest integer supported by Javascript is 9007199254740992. So that only your output is weird.
For Reference go through the link http://ecma262-5.com/ELS5_HTML.htm#Section_8.5
[edit] adjusted the answer based on Borodins comment.
Mmm, I think the result should be 2517052. I'd say this does the same:
var numbers = '342345820139586830203845861938475676'.split('')
,num = numbers.splice(0,2)
,result = Math.pow(num[0],num[1]);
while ( (num = numbers.splice(0,2)) && num.length ){
result += Math.pow(num[0],num[1]);
}
console.log(result); //=> 2517052
The array methods map and reduce are supported in modern browsers,
and could be worth defining in older browsers. This is a good opportunity,
if you haven't used them before.
If you are going to make an array of a string anyway,
match pairs of digits instead of splitting to single digits.
This example takes numbers or strings.
function sumPower(s){
return String(s).match(/\d{2}/g).map(function(itm){
return Math.pow(itm.charAt(0), itm.charAt(1));
}).reduce(function(a, b){
return a+b;
});
}
sumPower('342345820139586830203845861938475676');
alert(sumPower(s))
/*
returned value:(Number)
2517052
*/

not giving value after decimal point

This method gives me wrong value, why? Result must be 5.088100 but it gives me 5.o88100 in any value. If the first number after decmal point is zero then it removes it, why?
var precision = descriptor.digits ? descriptor.digits[1] : 2;
var int_part = Math.floor(value);
var dec_part = Math.abs(Math.floor((value % 1) * Math.pow(10, precision)));
Because you're turning the part after the decimal point into an integer, so 08 becomes 8 — just like var dec_part = 08 would give you 8.
If you want the decimal part use string manipulation:
var tmp = value.toFixed(precision).split("."),
int_part = tmp[0],
dec_part = tmp[1];
if you treat the dec_part as a number, if absolutely clear that the leading zeroes are droped off. numbers don't and can't have leading zeros.
what you're really trying to do is getting the two parts as strings, wich is a lot easier using split():
var parts = value.split(".");
var int_part = parts[0],
var dec_part = parts[1];
but at least, if you just want to round your value to a specific precision, you can just drop that complicated stuff out and use toFixed():
value = value.toFixed(precision);

Categories