Reputation: 36856
In most cases for me, i just want to check if string/number that i get is simple number only like this:
0, 1, 500, -1, 1.1, -1.1, 1.1013200 and so on.
And then convert it safely, without getting unexpected results.
What will be correct way to check if string or number is SIMPLE number?
Simple stands for:
Upvotes: 0
Views: 368
Reputation: 12864
You can parse it to number and parse this number to String another time. After test if the two variables is the same.
For scientific notations you can check if the string includes "e" or includes "NaN" for NaN
number
Like :
var num_s = " 898";
var num_n = Number(num_s)
var num2_s = "89.8";
var num2_n = Number(num2_s)
var num3_s = "1e+23";
var num3_n = Number(num3_s)
var num4_s = "NaN";
var num4_n = Number(num4_s)
console.log(num_s === String(num_n))
console.log(num2_s === String(num2_n))
console.log(num3_s === String(num3_n) && !num3_s.includes('e'))
console.log(num4_s === String(num4_n) && !num4_s.includes('NaN'))
You can create a function that test this cases like
function isSimpleNumber(num_s) {
var num_n = Number(num_s)
if (Number.isNaN(num_n) || num_n > Number.MAX_SAFE_INTEGER || num_n < Number.MIN_SAFE_INTEGER)
return false;
return num_s === String(num_n) && !num_s.includes('e');
}
Upvotes: 1
Reputation: 36856
Thanks to @Vlaz and R3tep i combined a function to make it work, only problem is .1 values, but cannot see a way to check it and they converted to and from without problems, it's ok.
const isSimpleNum = n => {
const nStr = String(n);
const nNum = Number(n);
if (nStr === "-0") return true;
if (nNum > Number.MAX_SAFE_INTEGER || nNum < Number.MIN_SAFE_INTEGER)
return false;
if (nStr === String(nNum) && !["e", "NaN"].some(e => nStr.includes(e))) {
return true;
} else {
return false;
}
};
const isTrue = ["1", "-1", 1, -1, 0, -0, "0", "-0", 1.1, -0.1, "0.1", "-0.1"];
const isFalse = [
"-0,1",
"080",
0.1,
".1",
" 898",
"a",
"1e+23",
"NaN",
undefined,
null,
NaN,
Infinity
];
isTrue.forEach((v, i) => {
if (!isSimpleNum(v)) {
console.log(`isTrue index ${i} as ${v} not passed`);
}
});
console.log("isTrue done");
isFalse.forEach((v, i) => {
if (isSimpleNum(v)) {
console.log(`isFalse index ${i} as ${v} not passed`);
}
});
console.log("isFalse done");
Upvotes: 1
Reputation: 28997
A somewhat "dumb" solution but you can convert the input to a number and check if it looks like the input again:
function canSafelyConvert(input) {
//convert to number
const numeric = Number(input);
//cannot convert
if (Number.isNaN(numeric))
return false;
//discard values that are going to cause problems
if (numeric > Number.MAX_SAFE_INTEGER || numeric < Number.MIN_SAFE_INTEGER)
return false;
let canonicalValue = input;
if(canonicalValue.includes(".")) {
//remove trailing zeries and the decimal dot, if nothing is left after it
canonicalValue = canonicalValue.replace(/\.?0+$/g, "")
}
//check if the converted value seems the same as the input
return String(numeric) === canonicalValue;
}
const testValues = [
//valid
"0",
"1",
"1.000",
"500",
"-1",
"1.1",
"-1.1",
"1.1013200",
//invalid
"1e+30",
" 1",
"080",
".1"
]
for (const value of testValues) {
console.log(value, ":", canSafelyConvert(value));
}
This will filter out any values that are different when converted to a JavaScript numeric.
NaN
would be produced and you can safely discard the output.1.2000
will be converted to 1.2
. You also have to strip a dangling decimal dot for the case where you get 1.000
which converts to 1
. This will include some that aren't actually different, e.g., Number(".1")
would produce 0.1
which is the correct conversion but it's explicitly mentioned to be incorrect.
Upvotes: 1
Reputation: 5181
Simply make a Regex check:
var reg = /^(0|-?[1-9]\d*\.?\d+)$/;
var value1 = '1e+30';
var value2 = ' 1';
var value3 = '.1';
var value4 = '01';
var value5 = '123';
var value6 = '1.2';
var value7 = '-1.2';
var reg = /^(0|-?[1-9]\d*\.?\d+)$/;
// This should be false
console.log(reg.test(value1))
// This should be false
console.log(reg.test(value2))
// This should be false
console.log(reg.test(value3))
// This should be false
console.log(reg.test(value4))
// This should be true
console.log(reg.test(value5))
// This should be true
console.log(reg.test(value6))
// This should be true
console.log(reg.test(value7))
-?
for 0 or 1 '-' Character\d+
for 1 or more numbers\.?
for 0 or 1 decimal seperatorFor more information there is a good documentation here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
Upvotes: 0
Reputation: 2530
Using regular expression and Number.MAX_SAFE_INTEGER
let num = '090071';
const regx = /(^0$)|(^[1-9][0-9.-]{1,}$)/;
console.log(regx.test(num) && Number(num) <= Number.MAX_SAFE_INTEGER)
Upvotes: 0