I came across a problem where I needed to determine if the field being entered by the user was an integer or float. The answer would then preselect a drop down further along a form. After much digging I found lots of framework code but none that actually did the job properly. The test data I used was;
Blank answer,
Non Numeric (Alpha),
1.0,
10,
1.10,
2.4,
3.0,
0.30,
0.00
A lot of other posts were also tested with the above data and I could not find one that passed ALL of the data correctly.
So I have written the following so that it may be reviewed by your good selves and hopefully it will help someone else out should they come across the same situation.
function isInteger(value)
{
//if(isNaN(value))return Nan;//optional check
//test for decimal point
if(!( /^-?\d+$/.test(String(value))))
{
//decimal point found
//if parseInt changes value it must be a float
if(parseInt(value) / 1 != value)return false;
}
//no decimal point so must be integer
return true;
}
Testing for integer values
ECMAScript 6 standard introduces a Number.isInteger().
This function is not yet supported by all major browsers, but a polyfill is listed on the site:
Number.isInteger = Number.isInteger || function isInteger (value) {
return typeof value === 'number' &&
isFinite(value) &&
Math.floor(value) === value
}
In case of user input (which is a string, not an integer), we can use the Number function to perform a type conversion into a number:
var input = '123' // Imagine this came from user
if (Number.isInteger(Number(input)) {
// User entered a valid integer value
}
Note, however, that the type conversion returns a valid integer-like value even for hexadecimal or octal strings. If this is not desired, you would need to further validate the original string. For detailed information about how the type conversion works, see MDN.
If such strict validation is desired, MDN also provides a good implementation using Regex (see the link for example output):
function filterInt (value) {
if(/^(\-|\+)?([0-9]+|Infinity)$/.test(value))
return Number(value)
return NaN
}
Testing for floating point numbers
isFinite() in combination with Number.isInteger() can help achieve our goal.
In case of user input (which is a string, not a float), we must use the Number function to perform a type conversion into a number:
var input = '123.5'
// Perform type conversion to a number
input = Number(input)
if (Number.isFinite(input) && ! Number.isInteger(input)) {
// A finite number that is not an integer can only be a float
}
Alternatively, a stricter variant of the parseFloat() implementation may be used instead, as listed on MDN (see the link for example output):
function filterFloat (value) {
if(/^(\-|\+)?([0-9]+(\.[0-9]+)?|Infinity)$/
.test(value))
return Number(value)
return NaN
}
Since you've mentioned user inputs, your question is about strings, so Number.isInteger is not an option.
To answer this question correctly we have to define more precisely what "integer" means when applied to strings. Is it
a sequence of digits? (example: ১২৪৫)
or a sequence of arabic digits? (example: 0000001)
or any mathematically valid integer representation? (example: 989238402389402394820394802)
or a mathematically valid integer that can be represented exactly in Javascript (i.e. it's less than MAX_SAFE_INTEGER)?
My guess is that you're looking for 4), here's the code for this case:
function isValidIntegerRepresentation(str) {
return /^-?\d+$/.test(str) && String(Number(str)) === str;
}
test = ['0', '00', '123', '-123', '239482039482309820394820394'];
test.forEach(function(n) {
document.write(n + "=" + isValidIntegerRepresentation(n) + "<br>");
});
This is very similar to what you already have.
Related
What if I want to store a very very large number and then display it. For example factorial of 200.
How can I do this using JavaScript?
I tried the normal way and the result is null or infinity.
function fact(input) {
if(input == 0) {
return 1;
}
return input * fact(input-1);
}
var result = fact(171);
console.log(result);
I tried in normal way and the result is infinity or null.
It seems JavaScript can generate Factorial up to 170.
Look at this picture. This calculator seems able to do it.
The BigInt numeric type is going to be implemented in the future of JavaScript, the proposal is on Stage 3 on the ECMAScript standardization process and it's being supported by major browsers now.
You can use either the BigInt constructor or the numeric literal by appending an n at the end of the number.
In older environments you can use a polyfill.
function fact(input) {
if(input == 0n) {
return 1n;
}
return input * fact(input-1n);
}
const result = fact(171n);
console.log(String(result));
Try this javascript based BigInteger library. There are many to choose from. But i recommend this one https://github.com/peterolson/BigInteger.js
Example:
var num = bigInt("9187239176928376598273465972639458726934756929837450")
.plus("78634075162394756297465927364597263489756289346592");
I'm doing my calculator and want prevent div to zero. I guess I must check last to elements if they are "/0"? what I'm doing wrong?
function div(input)
{
var input = document.getElementById("t");
var lastElement = (input.value.length-1);
//alert(input.value[lastElement-1]);
//alert(input.value[lastElement]);
if (input.value[lastElement-1] === "/")
{
if (input.value[lastElement] === "0")
{
alert(" / to Zero");
}
}
}
Use RegEx instead:
var is_div_by_zero = /\/[\s.0]+$/.test(value); // Returns true if it is divided by zero, false if otherwise
It matches:
/ 0
/0
/ 0
/ 000
/ 0.00000
etc.
As T.J. Crowder commented it is probably due to inconsistent formatting.
It would be better to work with the Javascript engine instead of going against it.
Just evaluate the entered formula and handle the exceptions thrown by the Javascript engine.
Place your evaluation code inside a try ... catch(e) block and handle the exceptions there.
try {
// your calculation code here, eg:
result = value1 / value2;
} catch (e) {
// this catches the error and provides the proper way of handling the errors,
// and your script doesn't die because of the error
// also, the e parameter contains the exception thrown, which provides info you can
// display
// or based on the error type come up with a proper solution
alert (e.message);
}
More info on Javascript error handling: http://javascript.info/tutorial/exceptions
Update
Forgot that, unfortunately, a division by zero does not result in an exception being thrown in Javascript. It will result in NaN for 0/0 and Infinity for x/0 (where x is any number). Infinity has the type number.
You can test for this after evaluating your equation.
My previous answer is one solution to your problem, but may bee too complicated for what would you like to achieve.
Instead of taking things from your input character by character, split your string on the operator and trim the parts. I will create the solution for two operands, and you can start from that.
var equation = document.getElementById("t").value;
var operands = equation.split('/');
var divisor = operands[operands.length - 1].trim();
// since the contents of your input are a string, the resulting element is also a string
if (parseFloat(divisor) == 0) {
alert("Division by zero");
}
This is a very rough approach, as you will have to validate and filter your input (no other things than numbers and valid operators should be allowed). Also, you will have to check for operation priority (do you allow multiple operators in your equation?) etc.
I am using javascript number.toFixed() function.
My problem is I have to explicitly mention number of fractional length like below:
if number is 1e11 then I have to specifiy it as
number.toFixed(2)
or if number is 1e1 then :
number.toFixed(1)
or if its 1e0 then
number.toFixed(0)
I want to do it dynamically based on whether fractions present or not. and irrespective of fractional length.
I dont want to pass parameter of fixed fractional length. js should dynamically understand fractional length of it. Is there similar provision in JS? or is there any similar function in java script where I need not to explicitly pass parameter of fixed length?
var temp = number.split('.');
if (typeof temp[1] !== 'undefined') {
console.log(temp[1].length); // here you got it
} else {
// 0
}
As a work around to not being able to filter inputs without directives I've attempted the following:
On the input ngChange detects a change and runs a function. The input has type="number"
<input type="number"
ng-model="ctrl.met.mass"
ng-change="ctrl.met.update.mass()">
The function updates some other fields, then formats them. In this example I want it to display two decimal points with toFixed(2). This is done with variable = variable.toFixed(2)
ctrl.met.cost = ctrl.met.mass * ctrl.met.price;
ctrl.imp.mass = ctrl.met.mass * 0.0353;
ctrl.imp.cost = ctrl.imp.mass * ctrl.imp.price;
console.log(typeof ctrl.met.mass); // number
ctrl.met.mass = ctrl.met.mass.toFixed(2);
console.log(typeof ctrl.met.mass); //string
But the number isn't formatting as well as I'm receiving this error; note the number at the end of the URL is 29.00, being the desired result. If the number is 12.34 that would be in place of 29.00.
Error: ngModel:numfmt
Model is not of type `number`
But when I run typeof ctrl.met.mass at any point, or any other variable I'm working with, it's telling me it is in fact a number except after .toFixed() has interacted with it.
The same error has occurred with the Angular Number Filter (after injecting), parseInt(), parseFloat(), and toPrecision() (to a precision of 4, to ensure two decimal places for a two digit number).
ctrl.met.mass = $filter("number")(ctrl.met.mass, 2);
ctrl.met.mass = $filter("number")(parseInt/Float/Precision(ctrl.met.mass), 2);
ctrl.met.mass = ctrl.met.mass.toInt/Float
ctrl.met.mass = ctrl.met.mass.Precision(4);
I'm thinking I won't be able to do so this way, and will need to use a directive. Before I try that though, why is this happening and can it be worked around?
edit: It seems what I'm trying is impossible. Upon setting ctrl.met.mass to what was, without a doubt, a number with two decimal places it rejected it in preference for an integer. If anyone knows why this is the case, please share.
The returned value from the toFixed method is a string. So you need to convert it to float in your controller:
var fixed = ctrl.met.mass.toFixed(2);
ctrl.met.mass = parseFloat(fixed);
you can make a stringToNumber directive to parse string to number, the perfect example of this is shown at below link :
https://docs.angularjs.org/error/ngModel/numfmt
I see many questions about methods to detect if a value is a floating-point number, but none of the examples work on numbers like as 1.0, 5.0, etc.
Is it possible to distinguish between numbers like 1 and 1.0 or 5 and 5.0? If yes, how can you detect a floating-point variable type?
In Ecmascript 6, you can use isInteger:
var value = . . .;
Number.isInteger(value);
However, this is not widely supported yet. For now, you can use this:
function isInteger(value) {
return typeof value === 'number' && (value | 0) === value;
}
This should work for all integer values that can be represented exactly in a 64-bit floating point representation.
I think the more concise answer is this one :
In javascript : 5 === 5.0.
So from this point on, no way can be found to distinguish them.
They are strictly the same thing.
Edit : reminder : the only x such as (x!==x) in javascript is NaN.
Zerstoren, the others are technically right: in javascript if you enter 2.0 or 2, there is no difference on how data is stored internally, so there is no way to find out if data was originally written as integer or float.
However, in case you want to validate some user form data, so that the user enters only integer numbers (e.g. order 2 pizzas, not 2.0) then the you do have a solution because that's actually a string (hence "2.0" is not same as "2"). You can use
typeof(n) =="string" && parseInt(n, 10) == n && n.indexOf('.')==-1
The first typeof condition is so that you fall under data is still in string format case I mentioned. See here: http://jsfiddle.net/X6U2d/
Andrei
There is no such thing as a float or int basic types in JavaScript, only a number. So, there is no difference between 5.0 and 5.
If it is important to you (for whatever reason), you will need to store the value as a string then use parseFloat to extract the value.
For example:
var int = "5";
var float = "5.0";
console.log(int == float); // false
console.log(parseFloat(int) == parseFloat(float)); // true
How to print numbers to fixed number of decimal places
I've just spotted Zerstoren comment: "i get data from mongodb and want to print this data with strong typing."
The method toFixed can be used to print a number to fixed number of decimal places:
var num = 5;
console.log( num.toFixed(1) ); // 5.0