Regex expression in javascript to validate number [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Simple regular expression for a decimal with a precision of 2
HI i need to validate a number using regex. The main idea is that i have the integer part, the decimal part and the decimal separator of a number. For example if i have this:
var integer_part = 4;
var decimal_part = 2;
var decimal_separator = ".";
// will be valid numbers
// 2546.33
// 12
// 1.33
// 263
// 0
can i make a regex string with the values in the variables to validate a string ¿?

You don't need a regex for this:
!isNaN(parseFloat(n)) && isFinite(n);
That checks a number is a float, isn't NaN and isn't infinity.
This sounds like an XY problem. What you should have asked is How can I validate a number? and left the regex part out.

Though it is not clear from your question, I am assuming you want to use the variables to determine the range of allowable values in your regex If so, you can make your pattern string like this:
pattern = '/[\d]{0,' + integer_part + '}(' + decimal_separator + '[\d]{1,' + decimal_part + '})?/';
This is a basic implementation. In this case, in order to use . as you separator you would actually want to set decimal_separator = '\.'; This is to escape the decimal which is wildcard match in regex.
If you really want to look for more edge cases, you might want to build up your pattern conditionally like this:
pattern = '/[\d]{0,' + integer_part + '}';
if (decimal_part > 0) {
if (decimal_separator == '.') {
pattern += '(\.';
} else {
pattern += '(' + decimal_separator;
}
pattern += '[\d]';
if (decimal_part == 1) {
pattern += '{1}';
} else {
pattern += '{1,' + decimal_part + '}';
}
pattern += ')?';
}
pattern += '/';

Just use this regex, it will look for anything with
\d+(\.\d+)
However, there might be a better way to do it.
Boolean isFloat=false;
try
{
float num=parseFloat(n);
isFloat=!isNaN(num) && isFinite(num);
}
catch (NumberFormatException ex)
{
//Isn't a number
}

Related

RegEx says all my inputs are false for a float number (JavaScript) [duplicate]

This question already has answers here:
Why do regex constructors need to be double escaped?
(5 answers)
Closed 6 years ago.
My objective is to check if the number that has been input into a form via HTML meets the following...
Is a number between 0.01 and 100.0
Is a float number e.g. will always of the format 00.01
My RegEx is - "\d{1,3}\.\d{1,2}" - Which when I check on RegExr appears to be correct... http://regexr.com/3eme3
However my code is returning false... Where am I going wrong?
(I've checked it both as a non parsed float number and as a parsed float number)
function checkAgeGrade(){
var ageGradeValue = document.getElementsByName("AgeGrade")[0].value;
console.log("Age Grade input: " + ageGradeValue);
var correctDigits = new RegExp("\d{1,3}\.\d{1,2}");
console.log("Correct digits: " + correctDigits);
if(!hasValue(ageGradeValue)){
document.submitrunnertime.AgeGrade.value = "-1";
}
console.log("has a value");
if(!isNaN(ageGradeValue)){
console.log("passed isNaN");
var parsedAgeGradeValue = parseFloat(ageGradeValue);
console.log(parsedAgeGradeValue);
if(parsedAgeGradeValue > 0.00 && parsedAgeGradeValue < 100.00){
console.log("range passed, value is: " + parsedAgeGradeValue + ", checking RegEx");
console.log("Parsed number: " + correctDigits.test(parsedAgeGradeValue));
console.log("Not Parsed number: " + correctDigits.test(ageGradeValue));
return correctDigits.test(parsedAgeGradeValue);
}
}
console.log("false function");
return false;
}
The function I am using to check to see if the input has a value or not is...
function hasValue(aValue) {
var whiteSpace = new RegExp("\s+");
if (aValue.length >= 1) {
if (whiteSpace.test(aValue)) {
return false;
} else {
return true;
}
return false;
}
Because you're creating your regular expression as a string (which, in this case, is not necessary), you need to double-escape the \d markers. Otherwise, the backslash will be ignored:
var correctDigits = new RegExp("\\d{1,3}\\.\\d{1,2}");
You can also do this:
var correctDigits = /\d{1,3}\.\d{1,2}/;
When you use native regular expression syntax, you don't have to double-escape like you do when the expression is in a string.

Evaluating numbers that include thousand separators

I understand that if the parseFloat function encounters any character other than numeric characters (0-9+-. and exponents) it just evaluates the number up to that character, discarding anything else.
I'm having a problem where I need to be able to validate numbers with thousand separators like so:
var number = "10,000.01"; //passes
var numberWithoutThousand = "10000.01"; //fails
//i.e:
if(parseFloat(number) <= 10000) {
return true;
}
//passess
problem is the above code returns true when technically that number is larger than 10,000.
What's the best way to get around this? I've considered stripping out the comma before testing the number, but not sure that is a good strategy.
You don't have numbers, you have strings, so just removing the comma is the way to go
number = number.replace(/\,/g, '');
Your "stripping the comma" strategy seems good to me.
if ( parseFloat( number.replace(",","") ) ) { etc(); }
As has been suggested, to have , in the number it must be a string and so do a search and replace. If you are having to do this on a regular basis then make yourself a reusable function.
Javascript
function myParseFloat(value) {
if (typeof value === 'string') {
value = value.replace(/,/g, '');
}
return parseFloat(value);
}
var number1 = "10,000.01",
number2 = "10000.01",
number3 = 10000.01;
console.log(myParseFloat(number1), myParseFloat(number2), myParseFloat(number3));
Output
10000.01 10000.01 10000.01
On jsFiddle

How to increment a numeric string by +1 with Javascript/jQuery

I have the following variable:
pageID = 7
I'd like to increment this number on a link:
$('#arrowRight').attr('href', 'page.html?='+pageID);
So this outputs 7, I'd like to append the link to say 8. But if I add +1:
$('#arrowRight').attr('href', 'page.html?='+pageID+1);
I get the following output: 1.html?=71 instead of 8.
How can I increment this number to be pageID+1?
Try this:
parseInt(pageID, 10) + 1
Accordint to your code:
$('#arrowRight').attr('href', 'page.html?='+ (parseInt(pageID, 10) + 1));
+ happens to be valid operator for both strings and numbers that gives different results when both arguments are numeric and when at least one is not. One of possible workarounds is to use operator that only have numeric context but gives same mathematical result, like -. some_var - -1 will always be same as adding 1 to some_var's numeric value, no matter if it is string or not.
$('#arrowRight').attr('href', 'page.html?='+ (pageID - -1));
All these solutions assume that your number you want to add 1 to is within the machine precision for an integer. So if you have a large enough number within that string when you add 1 to it won't change the number.
For Example:
parseInt('800000000000000000', 10) + 1 = 800000000000000000
So I wrote a quick solution to the problem
function addOne(s) {
let newNumber = '';
let continueAdding = true;
for (let i = s.length - 1; i>= 0; i--) {
if (continueAdding) {
let num = parseInt(s[i], 10) + 1;
if (num < 10) {
newNumber += num;
continueAdding = false;
} else {
newNumber += '0';
}
} else {
newNumber +=s[i];
}
}
return newNumber.split("").reverse().join("");
}
Now, using the same example above
addOne('800000000000000000') + 1 = '800000000000000001'
Note that it must stay as a string or you will lose that 1 at the end.
It needs to be a integer, not a string. Try this:
pageID = parseInt(pageID)+1;
Then you can do
$('#arrowRight').attr('href', 'page.html?='+pageID);
Simply, $('#arrowRight').attr('href', 'page.html?='+(pageID+1));
The parentheses makes the calculation done first before string concatenation.
let pageId = '7'
pageId++
console.log(pageId)
Nowadays, you just need to pageID++.
Just change your order of operations by wrapping your addition in parentheses; if pageID is already a number, parseInt() isn't necessary:
$('#arrowRight').attr('href', 'page.html?='+(pageID+1));
Demo
As long as your pageID is numeric, this should be sufficient:
$('#arrowRight').attr('href', 'page.html?='+(pageID+1));
The problem you were seeing is that JavaScript normally executes in left-to-right order, so the string on the left causes the + to be seen as a concatenator, so it adds the 7 to the string, and then adds 1 to the string including 7.

Convert String with Dot or Comma as decimal separator to number in JavaScript

An input element contains numbers a where comma or dot is used as decimal separator and space may be used to group thousands like this:
'1,2'
'110 000,23'
'100 1.23'
How would one convert them to a float number in the browser using JavaScript?
jQuery and jQuery UI are used. Number(string) returns NaN and parseFloat() stops on first space or comma.
Do a replace first:
parseFloat(str.replace(',','.').replace(' ',''))
I realise I'm late to the party, but I wanted a solution for this that properly handled digit grouping as well as different decimal separators for currencies. As none of these fully covered my use case I wrote my own solution which may be useful to others:
function parsePotentiallyGroupedFloat(stringValue) {
stringValue = stringValue.trim();
var result = stringValue.replace(/[^0-9]/g, '');
if (/[,\.]\d{2}$/.test(stringValue)) {
result = result.replace(/(\d{2})$/, '.$1');
}
return parseFloat(result);
}
This should strip out any non-digits and then check whether there was a decimal point (or comma) followed by two digits and insert the decimal point if needed.
It's worth noting that I aimed this specifically for currency and as such it assumes either no decimal places or exactly two. It's pretty hard to be sure about whether the first potential decimal point encountered is a decimal point or a digit grouping character (e.g., 1.542 could be 1542) unless you know the specifics of the current locale, but it should be easy enough to tailor this to your specific use case by changing \d{2}$ to something that will appropriately match what you expect to be after the decimal point.
The perfect solution
accounting.js is a tiny JavaScript library for number, money and currency formatting.
Check this for ref
You could replace all spaces by an empty string, all comas by dots and then parse it.
var str = "110 000,23";
var num = parseFloat(str.replace(/\s/g, "").replace(",", "."));
console.log(num);
I used a regex in the first one to be able to match all spaces, not just the first one.
This is the best solution
http://numeraljs.com/
numeral().unformat('0.02'); = 0.02
What about:
parseFloat(str.replace(' ', '').replace('.', '').replace(',', '.'));
All the other solutions require you to know the format in advance. I needed to detect(!) the format in every case and this is what I end up with.
function detectFloat(source) {
let float = accounting.unformat(source);
let posComma = source.indexOf(',');
if (posComma > -1) {
let posDot = source.indexOf('.');
if (posDot > -1 && posComma > posDot) {
let germanFloat = accounting.unformat(source, ',');
if (Math.abs(germanFloat) > Math.abs(float)) {
float = germanFloat;
}
} else {
// source = source.replace(/,/g, '.');
float = accounting.unformat(source, ',');
}
}
return float;
}
This was tested with the following cases:
const cases = {
"0": 0,
"10.12": 10.12,
"222.20": 222.20,
"-222.20": -222.20,
"+222,20": 222.20,
"-222,20": -222.20,
"-2.222,20": -2222.20,
"-11.111,20": -11111.20,
};
Suggestions welcome.
Here's a self-sufficient JS function that solves this (and other) problems for most European/US locales (primarily between US/German/Swedish number chunking and formatting ... as in the OP). I think it's an improvement on (and inspired by) Slawa's solution, and has no dependencies.
function realParseFloat(s)
{
s = s.replace(/[^\d,.-]/g, ''); // strip everything except numbers, dots, commas and negative sign
if (navigator.language.substring(0, 2) !== "de" && /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(s)) // if not in German locale and matches #,###.######
{
s = s.replace(/,/g, ''); // strip out commas
return parseFloat(s); // convert to number
}
else if (/^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(s)) // either in German locale or not match #,###.###### and now matches #.###,########
{
s = s.replace(/\./g, ''); // strip out dots
s = s.replace(/,/g, '.'); // replace comma with dot
return parseFloat(s);
}
else // try #,###.###### anyway
{
s = s.replace(/,/g, ''); // strip out commas
return parseFloat(s); // convert to number
}
}
Here is my solution that doesn't have any dependencies:
return value
.replace(/[^\d\-.,]/g, "") // Basic sanitization. Allows '-' for negative numbers
.replace(/,/g, ".") // Change all commas to periods
.replace(/\.(?=.*\.)/g, ""); // Remove all periods except the last one
(I left out the conversion to a number - that's probably just a parseFloat call if you don't care about JavaScript's precision problems with floats.)
The code assumes that:
Only commas and periods are used as decimal separators. (I'm not sure if locales exist that use other ones.)
The decimal part of the string does not use any separators.
try this...
var withComma = "23,3";
var withFloat = "23.3";
var compareValue = function(str){
var fixed = parseFloat(str.replace(',','.'))
if(fixed > 0){
console.log(true)
}else{
console.log(false);
}
}
compareValue(withComma);
compareValue(withFloat);
This answer accepts some edge cases that others don't:
Only thousand separator: 1.000.000 => 1000000
Exponentials: 1.000e3 => 1000e3 (1 million)
Run the code snippet to see all the test suite.
const REGEX_UNWANTED_CHARACTERS = /[^\d\-.,]/g
const REGEX_DASHES_EXEPT_BEGINNING = /(?!^)-/g
const REGEX_PERIODS_EXEPT_LAST = /\.(?=.*\.)/g
export function formatNumber(number) {
// Handle exponentials
if ((number.match(/e/g) ?? []).length === 1) {
const numberParts = number.split('e')
return `${formatNumber(numberParts[0])}e${formatNumber(numberParts[1])}`
}
const sanitizedNumber = number
.replace(REGEX_UNWANTED_CHARACTERS, '')
.replace(REGEX_DASHES_EXEPT_BEGINING, '')
// Handle only thousands separator
if (
((sanitizedNumber.match(/,/g) ?? []).length >= 2 && !sanitizedNumber.includes('.')) ||
((sanitizedNumber.match(/\./g) ?? []).length >= 2 && !sanitizedNumber.includes(','))
) {
return sanitizedNumber.replace(/[.,]/g, '')
}
return sanitizedNumber.replace(/,/g, '.').replace(REGEX_PERIODS_EXEPT_LAST, '')
}
function formatNumberToNumber(number) {
return Number(formatNumber(number))
}
const REGEX_UNWANTED_CHARACTERS = /[^\d\-.,]/g
const REGEX_DASHES_EXEPT_BEGINING = /(?!^)-/g
const REGEX_PERIODS_EXEPT_LAST = /\.(?=.*\.)/g
function formatNumber(number) {
if ((number.match(/e/g) ?? []).length === 1) {
const numberParts = number.split('e')
return `${formatNumber(numberParts[0])}e${formatNumber(numberParts[1])}`
}
const sanitizedNumber = number
.replace(REGEX_UNWANTED_CHARACTERS, '')
.replace(REGEX_DASHES_EXEPT_BEGINING, '')
if (
((sanitizedNumber.match(/,/g) ?? []).length >= 2 && !sanitizedNumber.includes('.')) ||
((sanitizedNumber.match(/\./g) ?? []).length >= 2 && !sanitizedNumber.includes(','))
) {
return sanitizedNumber.replace(/[.,]/g, '')
}
return sanitizedNumber.replace(/,/g, '.').replace(REGEX_PERIODS_EXEPT_LAST, '')
}
const testCases = [
'1',
'1.',
'1,',
'1.5',
'1,5',
'1,000.5',
'1.000,5',
'1,000,000.5',
'1.000.000,5',
'1,000,000',
'1.000.000',
'-1',
'-1.',
'-1,',
'-1.5',
'-1,5',
'-1,000.5',
'-1.000,5',
'-1,000,000.5',
'-1.000.000,5',
'-1,000,000',
'-1.000.000',
'1e3',
'1e-3',
'1e',
'-1e',
'1.000e3',
'1,000e-3',
'1.000,5e3',
'1,000.5e-3',
'1.000,5e1.000,5',
'1,000.5e-1,000.5',
'',
'a',
'a1',
'a-1',
'1a',
'-1a',
'1a1',
'1a-1',
'1-',
'-',
'1-1'
]
document.getElementById('tbody').innerHTML = testCases.reduce((total, input) => {
return `${total}<tr><td>${input}</td><td>${formatNumber(input)}</td></tr>`
}, '')
<table>
<thead><tr><th>Input</th><th>Output</th></tr></thead>
<tbody id="tbody"></tbody>
</table>
From number to currency string is easy through Number.prototype.toLocaleString. However the reverse seems to be a common problem. The thousands separator and decimal point may not be obtained in the JS standard.
In this particular question the thousands separator is a white space " " but in many cases it can be a period "." and decimal point can be a comma ",". Such as in 1 000 000,00 or 1.000.000,00. Then this is how i convert it into a proper floating point number.
var price = "1 000.000,99",
value = +price.replace(/(\.|\s)|(\,)/g,(m,p1,p2) => p1 ? "" : ".");
console.log(value);
So the replacer callback takes "1.000.000,00" and converts it into "1000000.00". After that + in the front of the resulting string coerces it into a number.
This function is actually quite handy. For instance if you replace the p1 = "" part with p1 = "," in the callback function, an input of 1.000.000,00 would result 1,000,000.00

textbox validation accepting Ports in javascript

the question was accepting one or many ports that has one space between them with help of friends,
I used this one for my answer but for example if I enter 88888 it will alert me such this thing:
88888NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN is not correct
how can I correct this
<script type="text/javascript">
function portvalidating(field)
{
var output='';
m=field.value;
if(/^\d{1,5}([ ]\d{1,5})*$/.test(m))
{
var parts = m.split(' ');
for(i in parts)
{
var p= parseInt(parts[i]);
if(!((0 <= p) && (p<= 65535) && !isNaN(p)))
{
output+=p;
}
}
if(output=='')
var dummy=1;
else alert(output+'is not correct');
}
else alert('please enter a valid port!');
}
Unfortunately, regular expressions can't handle 'ranges', so you can't do this exactly as you want with regexp (therorically you can, but the regex would be hiper,hiper long).
However, you could validate your space-separated numbers with this regexp:
/^\d{1,5}([ ]\d{1,5})*$/
This will do what you want, except validating the range you supplied. But it controls that numbers have between 1 and 5 digits, and the other things you asked.
Hope this helps. Cheers
A crude regex without much error checking would be: exp = /\d{1,5}/g and then call .match(exp) on your string. However, you will need to use parseInt to convert the output to a number so that you can check it's value against your constraints.
I think you may be able to do this easier without Regex. Some quick code to split and parse a string is:
var s = "21 456 -32 70000";
var parts = s.split(' ');
var output;
for(i in parts)
{
p = parseInt(parts[i]);
if( (0 <= p) && (p <= 65535) && !isNaN(p) )
output += p+"<br />";
}
Hopefully this helps to some degree.
I think you would compromise your performance here if you want you are trying to validate a simple Integer value via RegEx.
IMO, try spiting the string with Space (' ') and and convert each value to Integer and perform myInt < 65535.
for( String str : portNumbers.split(' ') ){
try{
int i = Integer.parseInteger( str );
if( 0 > i && i > 65535 ){
errorMessage = str + " is out of range.";
}
}catch (NumberFormatException e) {
errorMessage = str + " is not a valid port.";
}
}
(6553[0-5]|655[0-2][0-9]|65[0-4][0-9][0-9]|6[0-4][0-9][0-9][0-9]|\d{2,4}|[1-9])

Categories

Resources