How to find that a number is float
or integer
?
1.25 --> float
1 --> integer
0 --> integer
0.25 --> float
<
Here are efficient functions that check if the value is a number or can be safely converted to a number:
function isNumber(value) {
if ((undefined === value) || (null === value)) {
return false;
}
if (typeof value == 'number') {
return true;
}
return !isNaN(value - 0);
}
And for integers (would return false if the value is a float):
function isInteger(value) {
if ((undefined === value) || (null === value)) {
return false;
}
return value % 1 == 0;
}
The efficiency here is that parseInt (or parseNumber) are avoided when the value already is a number. Both parsing functions always convert to string first and then attempt to parse that string, which would be a waste if the value already is a number.
Thank you to the other posts here for providing further ideas for optimization!
function int(a) {
return a - a === 0 && a.toString(32).indexOf('.') === -1
}
function float(a) {
return a - a === 0 && a.toString(32).indexOf('.') !== -1
}
You can add typeof a === 'number'
if you want to exclude strings.
!!(24%1) // false
!!(24.2%1) // true
function isInteger(n) {
return ((typeof n==='number')&&(n%1===0));
}
function isFloat(n) {
return ((typeof n==='number')&&(n%1!==0));
}
function isNumber(n) {
return (typeof n==='number');
}
function isInteger(x) { return typeof x === "number" && isFinite(x) && Math.floor(x) === x; }
function isFloat(x) { return !!(x % 1); }
// give it a spin
isInteger(1.0); // true
isFloat(1.0); // false
isFloat(1.2); // true
isInteger(1.2); // false
isFloat(1); // false
isInteger(1); // true
isFloat(2e+2); // false
isInteger(2e+2); // true
isFloat('1'); // false
isInteger('1'); // false
isFloat(NaN); // false
isInteger(NaN); // false
isFloat(null); // false
isInteger(null); // false
isFloat(undefined); // false
isInteger(undefined); // false
I like this little function, which will return true for both positive and negative integers:
function isInt(val) {
return ["string","number"].indexOf(typeof(val)) > -1 && val !== '' && !isNaN(val+".0");
}
This works because 1 or "1" becomes "1.0", which isNaN() returns false on (which we then negate and return), but 1.0 or "1.0" becomes "1.0.0", while "string" becomes "string.0", neither of which are numbers, so isNaN() returns false (and, again, gets negated).
If you only want positive integers, there's this variant:
function isPositiveInt(val) {
return ["string","number"].indexOf(typeof(val)) > -1 && val !== '' && !isNaN("0"+val);
}
or, for negative integers:
function isNegativeInt(val) {
return `["string","number"].indexOf(typeof(val)) > -1` && val !== '' && isNaN("0"+val);
}
isPositiveInt() works by moving the concatenated numeric string ahead of the value to be tested. For example, isPositiveInt(1) results in isNaN() evaluating "01", which evaluates false. Meanwhile, isPositiveInt(-1) results in isNaN() evaluating "0-1", which evaluates true. We negate the return value and that gives us what we want. isNegativeInt() works similarly, but without negating the return value of isNaN().
Edit:
My original implementation would also return true on arrays and empty strings. This implementation doe not have that defect. It also has the benefit of returning early if val is not a string or number, or if it's an empty string, making it faster in these cases. You can further modify it by replacing the first two clauses with
typeof(val) != "number"
if you only want to match literal numbers (and not strings)
Edit:
I can't post comments yet, so I'm adding this to my answer. The benchmark posted by @Asok is very informative; however, the fastest function does not fit the requirements, as it also returns TRUE for floats, arrays, booleans, and empty strings.
I created the following test suite to test each of the functions, adding my answer to the list, as well (function 8, which parses strings, and function 9, which does not):
funcs = [
function(n) {
return n % 1 == 0;
},
function(n) {
return typeof n === 'number' && n % 1 == 0;
},
function(n) {
return typeof n === 'number' && parseFloat(n) == parseInt(n, 10) && !isNaN(n);
},
function(n) {
return n.toString().indexOf('.') === -1;
},
function(n) {
return n === +n && n === (n|0);
},
function(n) {
return parseInt(n) === n;
},
function(n) {
return /^-?[0-9]+$/.test(n.toString());
},
function(n) {
if ((undefined === n) || (null === n)) {
return false;
}
if (typeof n == 'number') {
return true;
}
return !isNaN(n - 0);
},
function(n) {
return ["string","number"].indexOf(typeof(n)) > -1 && n !== '' && !isNaN(n+".0");
}
];
vals = [
[1,true],
[-1,true],
[1.1,false],
[-1.1,false],
[[],false],
[{},false],
[true,false],
[false,false],
[null,false],
["",false],
["a",false],
["1",null],
["-1",null],
["1.1",null],
["-1.1",null]
];
for (var i in funcs) {
var pass = true;
console.log("Testing function "+i);
for (var ii in vals) {
var n = vals[ii][0];
var ns;
if (n === null) {
ns = n+"";
} else {
switch (typeof(n)) {
case "string":
ns = "'" + n + "'";
break;
case "object":
ns = Object.prototype.toString.call(n);
break;
default:
ns = n;
}
ns = "("+typeof(n)+") "+ns;
}
var x = vals[ii][1];
var xs;
if (x === null) {
xs = "(ANY)";
} else {
switch (typeof(x)) {
case "string":
xs = "'" + n + "'";
break;
case "object":
xs = Object.prototype.toString.call(x);
break;
default:
xs = x;
}
xs = "("+typeof(x)+") "+xs;
}
var rms;
try {
var r = funcs[i](n);
var rs;
if (r === null) {
rs = r+"";
} else {
switch (typeof(r)) {
case "string":
rs = "'" + r + "'";
break;
case "object":
rs = Object.prototype.toString.call(r);
break;
default:
rs = r;
}
rs = "("+typeof(r)+") "+rs;
}
var m;
var ms;
if (x === null) {
m = true;
ms = "N/A";
} else if (typeof(x) == 'object') {
m = (xs === rs);
ms = m;
} else {
m = (x === r);
ms = m;
}
if (!m) {
pass = false;
}
rms = "Result: "+rs+", Match: "+ms;
} catch (e) {
rms = "Test skipped; function threw exception!"
}
console.log(" Value: "+ns+", Expect: "+xs+", "+rms);
}
console.log(pass ? "PASS!" : "FAIL!");
}
I also reran the benchmark with function #8 added to the list. I won't post the result, as they're a bit embarrassing (e.g. that function is NOT fast)...
The (abridged -- I removed successful tests, since the output is quite long) results are as follows:
Testing function 0
Value: (object) [object Array], Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) true, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) false, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: null, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) '', Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) '1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
FAIL!
Testing function 1
Value: (string) '1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!
Testing function 2
Value: (string) '1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!
Testing function 3
Value: (object) true, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (object) false, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) [object Array], Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) [object Object], Expect: (boolean) false, Result: (boolean) true, Match: false
Value: null, Expect: (boolean) false, Test skipped; function threw exception!
Value: (string) '', Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) 'a', Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) '1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
FAIL!
Testing function 4
Value: (string) '1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!
Testing function 5
Value: (string) '1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!
Testing function 6
Value: null, Expect: (boolean) false, Test skipped; function threw exception!
Value: (string) '1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!
Testing function 7
Value: (number) 1.1, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (number) -1.1, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (object) true, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) [object Array], Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) [object Object], Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) '', Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) '1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) true, Match: N/A
FAIL!
Testing function 8
Value: (string) '1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!
Testing function 9
Value: (string) '1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!
I've left in failures so you can see where each function is failing, and the (string) '#' tests so you can see how each function handles integer and float values in strings, as some may want these parsed as numbers and some may not.
Out of the 10 functions tested, the ones that actually fit OP's requirements are [1,3,5,6,8,9]