Reputation: 151
I am making an app, and I have some inputs, but I only want to accept numbers from 0 to 4, and they can have decimals, but only .5
. In other words, 0, 0.5, 1, 1.5, 2, 2.5, ..., 3.5, 4. Only these numbers should return true. However, an if statement like this would be very long, and I thought a regular expression would be far more efficient, but I have no idea how to do this.
If anyone could help me, it would be very nice.
Upvotes: 0
Views: 241
Reputation: 28962
Here are some non-regex solutions:
There is a little trick that can be used - the remainder operator %
can be used with 0.5
to check if the number is divisible by 0.5
. A check can simply be - if it's greater or equal to 0
, if it's less or equal to 4
and if it's divisible by 0.5
, so it only accepts numbers that have no decimal part (essentially .0
) or if the decimal part is .5
.
This produces a very concise validation:
const check = x =>
x >= 0 && x <= 4 && x % 0.5 === 0;
const check = x =>
x >= 0 && x <= 4 && x % 0.5 === 0;
test(0);
test(0.5);
test(1);
test(1.5);
test(2);
test(2.5);
test(3);
test(3.5);
test(4);
test(0.2)
test(1.25)
test(3.75)
test(4.5);
function test(num) {
const displayNum = `[${num}]`.padEnd(6, " ");
console.log(`${displayNum}: ${check(num)}`);
}
This may not work for any divisor! 0.5
is special as it's a power of two (2-1) so it plays nice with the floating point arithmetic. Not all numbers do that:
console.log(30 % 3)
console.log(3 % 0.3)
You can also get the decimal part by splitting the string representation of the number on .
. This allows for easier checking of any decimal part that's not a power of two.
Here is a robust check to allow you to pass any number - whether it's as a string or not.
const check = input => {
const str = String(input);
const num = Number(input);
const decimal = Number(str.split(".")[1]) || 0;
return !Number.isNaN(num) //input is a valid number
&& num >= 0 // more than zero
&& num <= 4 // less than four
&& (decimal === 0 || decimal === 5) //decimal is zero or five
}
const check = input => {
const str = String(input);
const num = Number(input);
const decimal = Number(str.split(".")[1]) || 0;
return !Number.isNaN(num)
&& num >= 0
&& num <= 4
&& (decimal === 0 || decimal === 5)
}
test(0);
test(0.5);
test(".5");
test(1);
test("1.0");
test(1.5);
test(2);
test("2.00");
test(2.5);
test(3);
test(3.5);
test("3.0000");
test(4);
test("4.");
test(0.2)
test(1.25)
test(3.75)
test(4.5);
function test(num) {
const displayNum = `[${num}]`.padEnd(8, " ");
console.log(`${displayNum}: ${check(num)}`);
}
If only numbers are expected it can be simplified to :
const check = num => {
const decimal = Number(String(num).split(".")[1]) || 0;
return !Number.isNaN(num)
&& num >= 0
&& num <= 4
&& (decimal === 0 || decimal === 5)
}
const check = num => {
const decimal = Number(String(num).split(".")[1]) || 0;
return num >= 0 && num <= 4
&& (decimal === 0 || decimal === 5)
}
test(0);
test(0.5);
test(1);
test(1.5);
test(2);
test(2.5);
test(3);
test(3.5);
test(4);
test(0.2)
test(1.25)
test(3.75)
test(4.5);
function test(num) {
const displayNum = `[${num}]`.padEnd(8, " ");
console.log(`${displayNum}: ${check(num)}`);
}
And generalises to
const makeRangeChecker = ({min = 0, max = 100, allowedDecimals = []}) => num => {
const decimal = Number(String(num).split(".")[1]) || 0;
return num >= min && num <= max
&& allowedDecimals.includes(decimal);
}
const check = makeRangeChecker({min: 0, max: 4, allowedDecimals: [0, 5]});
const makeRangeChecker = ({min = 0, max = 100, allowedDecimals = []}) => num => {
const decimal = Number(String(num).split(".")[1]) || 0;
return num >= min && num <= max
&& allowedDecimals.includes(decimal);
}
const check = makeRangeChecker({min: 0, max: 4, allowedDecimals: [0, 5]});
test(0);
test(0.5);
test(1);
test(1.5);
test(2);
test(2.5);
test(3);
test(3.5);
test(4);
test(0.2)
test(1.25)
test(3.75)
test(4.5);
function test(num) {
const displayNum = `[${num}]`.padEnd(8, " ");
console.log(`${displayNum}: ${check(num)}`);
}
If you're taking user input from the page, you can just use the normal HTML validation:
<div>Enter a number and change the focus to validate:</div>
<input type="number" step="0.5" min="0" max="4">
Upvotes: 2
Reputation: 20669
As VLAZ mentioned, it would be better to use a numeric comparison to do it.
But if you are insist, you could use following regex:
^(?!4\.5)[0-4](?:\.[05])?$
I'm also allowing trailing .0
s like 1.0
for better flexibility.
^
: the beginning of the string(?!4\.5)
: 4.5
is not allowed[0-4]
: a number from 0
to 4
(?:\.[05])?
: with an optional decimal point .0
or .5
$
: end of the stringSee the proof
Upvotes: 2