Jquery leave only two numbers after decimal point - javascript

Been looking for this a while now, most questions include same answers which I have tried and it did not work for my case, hence why I am posting this. Now my script returns several numbers and I want to leave those numbers and 2 numbers after the decimal point, now the problem is that I have another script that adds commas to those numbers, so for example, I might get following numbers.
56,883.90,607,219,945
5,327.078,363,188,421
1688.7000000000003
2,739.272
Now I have tried several stuff, including Number(number).toFixed(2), etc. But it would cut off some parts, for example.
first number above would return > "56.00", While I need it to return 56,883.90
Would return > "5.00", While I need 5,327.07
would return what I am expecting "1688.70"
Would return "2.00" instead of 2,739.27
Now I understand where the issue is, it takes comma and turns number afterwards, is there way to specifically grab only 2 numbers after the DOT?
Thanks in advance

Use Regex:
'56,883.90,607,219,945'.replace(/(\..{2}).*/,'$1')
Which matches all of your expected results:
56,883.90,607,219,945 => 56,883.90
5,327.078,363,188,421 => 5,327.07
1688.7000000000003 => 1688.70 (it will not add comma)
2,739.272 => 2,739.27
function changeToNumber(str) {
return str.replace(/(\..{2}).*/, '$1');
}
var input = ['56,883.90,607,219,945',
'5,327.078,363,188,421',
'1688.7000000000003',
'2,739.272'
]
input.forEach(function(value) {
console.log(changeToNumber(value));
});

You have to remove the , from the number string to parse the full number. Use String#replace method to remove , from the string.
Number('5,327.078'.replace(/,/g, ''))
console.log(Number('5,327.078'.replace(/,/g, '')).toFixed(2));

Related

Why doesn't my function correctly replace when using some regex pattern

This is an extension of this SO question
I made a function to see if i can correctly format any number. The answers below work on tools like https://regex101.com and https://regexr.com/, but not within my function(tried in node and browser):
const
const format = (num, regex) => String(num).replace(regex, '$1')
Basically given any whole number, it should not exceed 15 significant digits. Given any decimal, it should not exceed 2 decimal points.
so...
Now
format(0.12345678901234567890, /^\d{1,13}(\.\d{1,2}|\d{0,2})$/)
returns 0.123456789012345678 instead of 0.123456789012345
but
format(0.123456789012345,/^-?(\d*\.?\d{0,2}).*/)
returns number formatted to 2 deimal points as expected.
Let me try to explain what's going on.
For the given input 0.12345678901234567890 and the regex /^\d{1,13}(\.\d{1,2}|\d{0,2})$/, let's go step by step and see what's happening.
^\d{1,13} Does indeed match the start of the string 0
(\. Now you've opened a new group, and it does match .
\d{1,2} It does find the digits 1 and 2
|\d{0,2} So this part is skipped
) So this is the end of your capture group.
$ This indicates the end of the string, but it won't match, because you've still got 345678901234567890 remaining.
Javascript returns the whole string because the match failed in the end.
Let's try removing $ at the end, to become /^\d{1,13}(\.\d{1,2}|\d{0,2})/
You'd get back ".12345678901234567890". This generates a couple of questions.
Why did the preceding 0 get removed?
Because it was not part of your matching group, enclosed with ().
Why did we not get only two decimal places, i.e. .12?
Remember that you're doing a replace. Which means that by default, the original string will be kept in place, only the parts that match will get replaced. Since 345678901234567890 was not part of the match, it was left intact. The only part that matched was 0.12.
Answer to title question: your function doesn't replace, because there's nothing to replace - the regex doesn't match anything in the string. csb's answer explains that in all details.
But that's perhaps not the answer you really need.
Now, it seems like you have an XY problem. You ask why your call to .replace() doesn't work, but .replace() is definitely not a function you should use. Role of .replace() is replacing parts of string, while you actually want to create a different string. Moreover, in the comments you suggest that your formatting is not only for presenting data to user, but you also intend to use it in some further computation. You also mention cryptocurriencies.
Let's cope with these problems one-by-one.
What to do instead of replace?
Well, just produce the string you need instead of replacing something in the string you don't like. There are some edge cases. Instead of writing all-in-one regex, just handle them one-by-one.
The following code is definitely not best possible, but it's main aim is to be simple and show exactly what is going on.
function format(n) {
const max_significant_digits = 15;
const max_precision = 2;
let digits_before_decimal_point;
if (n < 0) {
// Don't count minus sign.
digits_before_decimal_point = n.toFixed(0).length - 1;
} else {
digits_before_decimal_point = n.toFixed(0).length;
}
if (digits_before_decimal_point > max_significant_digits) {
throw new Error('No good representation for this number');
}
const available_significant_digits_for_precision =
Math.max(0, max_significant_digits - digits_before_decimal_point);
const effective_max_precision =
Math.min(max_precision, available_significant_digits_for_precision);
const with_trailing_zeroes = n.toFixed(effective_max_precision);
// I want to keep the string and change just matching part,
// so here .replace() is a proper method to use.
const withouth_trailing_zeroes = with_trailing_zeroes.replace(/\.?0*$/, '');
return withouth_trailing_zeroes;
}
So, you got the number formatted the way you want. What now?
What can you use this string for?
Well, you can display it to the user. And that's mostly it. The value was rounded to (1) represent it in a different base and (2) fit in limited precision, so it's pretty much useless for any computation. And, BTW, why would you convert it to String in the first place, if what you want is a number?
Was the value you are trying to print ever useful in the first place?
Well, that's the most serious question here. Because, you know, floating point numbers are tricky. And they are absolutely abysmal for representing money. So, most likely the number you are trying to format is already a wrong number.
What to use instead?
Fixed-point arithmetic is the most obvious answer. Works most of the time. However, it's pretty tricky in JS, where number may slip into floating-point representation almost any time. So, it's better to use decimal arithmetic library. Optionally, switch to a language that has built-in bignums and decimals, like Python.

Regex replace for commas in the thousands

I have a Javascript function I'm using to loop through a bunch of inputs on a page and convert them to a thousands-compatible comma system. In short, regardless of what the user types into the field, they'll get a friendly thousands-separated number back.
Input: 5000
Return: 5,000
Here's how the function breaks down
function add_commas()
{
$('.field-group .field input[type=text]').each(function()
{
// format number
$(this).val(function(index, value) {
return value
.replace(/\D/g, "")
.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
;
});
});
}
Everything's working right except for one thing. Here's another example of the data being passed in and what's returned:
Input: 9.5
Return: 95
Note the whole number.
I'm wondering if there's a way to ignore or leave off the decimal if it didn't have one, but keep it and treat it respectfully if there is one. Here's the input/output as I would hope for:
Input: 5000
Return: 5,000
Input: 9.5
Return: 9.5
Input: 1000.50
Return: 1,000.50
Hopefully this was clear, but please do let me know if you require more information about the issue at hand. Thank you!
Actually regular expressions are not appropriate for this problem, because not every culture uses commas as thousands separators and periods for the radix separator. You should be using toLocaleString. In node, for example:
> (52342.214).toLocaleString()
'52,342.214'
> (52342.214).toLocaleString('de-DE')
'52.342,214'
> (52342.214).toLocaleString('ar-EG')
'٥٢٬٣٤٢٫٢١٤'
> (5234289877.21).toLocaleString('en-US')
'5,234,289,877.21'
This way you don't have to write your own error-prone code and you can localize for different cultures. The work has already been done for you!
You also get the zeros part of your question for free too! Notice:
> (38209).toLocaleString()
'38,209'
> (38209.0000).toLocaleString()
'38,209'
Again, all for free!
Change the first replace because it is removing the dot in the string
.replace(/[^0-9\.]/g, "")

Javascript convert string to integer

I am just dipping my toe into the confusing world of javascript, more out of necessity than desire and I have come across a problem of adding two integers.
1,700.00 + 500.00
returns 1,700.00500.00
So after some research I see that 1,700.00 is being treated as a string and that I need to convert it.
The most relevant pages I read to resolve this were this question and this page. However when I use
parseInt(string, radix)
it returns 1. Am I using the wrong function or the an incorrect radix (being honest I can't get my head around how I decide which radix to use).
var a="1,700.00";
var b=500.00;
parseInt(a, 10);
Basic Answer
The reason parseInt is not working is because of the comma. You could remove the comma using a regex such as:
var num = '1,700.00';
num = num.replace(/\,/g,'');
This will return a string with a number in it. Now you can parseInt. If you do not choose a radix it will default to 10 which was the correct value to use here.
num = parseInt(num);
Do this for each of your string numbers before adding them and everything should work.
More information
How the replace works:
More information on replace at mdn:
`/` - start
`\,` - escaped comma
`/` - end
`g` - search globally
The global search will look for all matches (it would stop after the first match without this)
'' replace the matched sections with an empty string, essentially deleting them.
Regular Expressions
A great tool to test regular expressions: Rubular and more info about them at mdn
If you are looking for a good tutorial here is one.
ParseInt and Rounding, parseFloat
parseInt always rounds to the nearest integer. If you need decimal places there are a couple of tricks you can use. Here is my favorite:
2 places: `num = parseInt(num * 100) / 100;`
3 places: `num = parseInt(num * 1000) / 1000;`
For more information on parseInt look at mdn.
parseFloat could also be used if you do not want rounding. I assumed you did as the title was convert to an integer. A good example of this was written by #fr0zenFry below. He pointed out that parseFloat also does not take a radix so it is always in base10. For more info see mdn.
Try using replace() to replace a , with nothing and then parseFloat() to get the number as float. From the variables in OP, it appears that there may be fractional numbers too, so, parseInt() may not work well in such cases(digits after decimal will be stripped off).
Use regex inside replace() to get rid of each appearance of ,.
var a = parseFloat('1,700.00'.replace(/,/g, ''));
var b = parseFloat('500.00'.replace(/,/g, ''));
var sum = a+b;
This should give you correct result even if your number is fractional like 1,700.55.
If I go by the title of your question, you need an integer. For this you can use parseInt(string, radix). It works without a radix but it is always a good idea to specify this because you never know how browsers may behave(for example, see comment #Royi Namir). This function will round off the string to nearest integer value.
var a = parseInt('1,700.00'.replace(/,/g, ''), 10); //radix 10 will return base10 value
var b = parseInt('500.00'.replace(/,/g, ''), 10);
var sum = a+b;
Note that a radix is not required in parseFloat(), it will always return a decimal/base10 value. Also, it will it will strip off any extra zeroes at the end after decimal point(ex: 17500.50 becomes 17500.5 and 17500.00 becomes 17500). If you need to get 2 decimal places always, append another function toFixed(decimal places).
var a = parseFloat('1,700.00'.replace(/,/g, ''));
var b = parseFloat('500.00'.replace(/,/g, ''));
var sum = (a+b).toFixed(2); //change argument in toFixed() as you need
// 2200.00
Another alternative to this was given by #EpiphanyMachine which will need you to multiply and then later divide every value by 100. This may become a problem if you want to change decimal places in future, you will have to change multiplication/division factor for every variable. With toFixed(), you just change the argument. But remember that toFixed() changes the number back to string unlike #EpiphanyMachine solution. So you will be your own judge.
try this :
parseFloat(a.replace(/,/g, ''));
it will work also on : 1,800,300.33
Example :
parseFloat('1,700,800.010'.replace(/,/g, '')) //1700800.01
Javascript doesn't understand that comma. Remove it like this:
a.replace(',', '')
Once you've gotten rid of the comma, the string should be parsed with no problem.

Add comma separator to a value variable

I have read some thousand comma separator JavaScript question/answer but found it hard to apply it in practice. For example I have the variable
x = 10023871234981029898198264897123897.231241235
How will I separate it in thousands with commas? I want a function that not only works with that number of digits but more. Regardless of the number of digits the function I need has to separate the number in commas and leaving the digits after the decimal point as it is, Can anyone help? It has to work on number and turn it into string.
First of all, for such huge numbers you should use string format:
var x = "10023871234981029898198264897123897.231241235";
Otherwise, JavaScript will automatically convert it to exponential notation, i.e. 1.002387123498103e+34.
Then, according to the question about money formatting, you can use the following code:
x.replace(/(\d)(?=(\d{3})+\.)/g, "$1,");
It will result in: "10,023,871,234,981,029,898,198,264,897,123,897.231241235".

Find numbers at a specific position

I'm trying to find an expression for JavaScript which gives me the two characters at a specific position.
It's always the same call so its may be not too complicated.
I have always a 10 char long number and i want to replace the first two, the two at place 3 and 4 or the two at place 5 and 6 and so on.
So far I've done this:
number.replace(/\d{2}/, index));
this replace my first 2 digits with 2 others digits.
but now I want to include some variables at which position the digits should be replaced, something like:
number.replace(/\d{atposx,atpox+1}/, index));
that means:
01234567891
and I want sometimes to replace 01 with 02 and sometimes 23 with 56.
(or something like this with other numbers).
I hope I pointed out what I want.
This function works fine:
function replaceChars(input, startPos, replacement){
return input.substring(0,startPos) +
replacement +
input.substring(startPos+replacement.length)
}
Usage:
replaceChars("0123456789",2,"55") // output: 0155456789
Live example: http://jsfiddle.net/FnkpT/
Numbers are fairly easily interpreted as strings in JS. So, if you're working with an actual number (i.e. 9876543210) and not a number that's represented by a string (i.e. '987654321'), just turn the number into a string (''.concat(number); ) and don't limit yourself to the constraints of what you can do with just numbers.
Both of the above examples are fine (bah, they beat me to it), but you can even think about it like this:
var numberString = ''.concat(number);
var numberChunks = numberString.match(/(\d{2})/g);
You've now got an array of chunks that you can either walk through, switch through, or whatever other kind of flow you want to follow. When you're done, just say...
numberString = numberChunks.join('');
number = parseInt(numberString, 10);
You've got your number back as a native number (or skip the last part to just get the string back). And, aside from that, if you're doing multiple replacements.. the more replacements you do in the number, the more efficient breaking it up into chunks and dealing with the chunks are. I did a quick test, and running the 'replaceChars' function was faster on a single change, but will be slower than just splitting into an array if you're doing two or more changes to the data.
Hope that makes sense!
You can try this
function replaceAtIndex(str,value,index) {
return str.substr(0,index)+value+str.substr(index+value.length);
}
replaceAtIndex('0123456789','X',3); // returns "012X456789"
replaceAtIndex('0123456789','XY',3); // returns "012XY56789"

Categories

Resources