Ask user for a number. Determine if the number is even or odd. I have my constants set and using modulo to figure this out. However I am stuck in an infinite loop and can't figure out why. I have my if statement in the loop as well as a break statement to get out, but still in an infinite loop.
HAVE TO USE A WHILE LOOP
// declare constants
const MODULO = 2;
const EVEN = 0;
const ODD = 1;
// declare variables
var enteredNumber;
var result;
// prompt user to enter an even number
enteredNumber = prompt("Enter an even number: ");
// convert user input into a number
enteredNumber = Number(enteredNumber);
// determine result of modulo equation
result = enteredNumber % MODULO;
// while loop to check if enteredNumber is even or odd
while (result === EVEN) {
document.write(enteredNumber + " is an even number <br/>");
enteredNumber = prompt("Enter an even number: ");
enteredNumber = Number(enteredNumber);
result = enteredNumber % MODULO;
if (result === ODD) {
document.write(enteredNumber + " isn't an even number");
break;
}
}
You can essentially one-liner this thing. You're already checking stuff with the while.
document.addEventListener('DOMContentLoaded', () => {
while (!(parseInt(window.prompt('Enter an even number', '2') || '1', 10) % 2)) { };
});
Why this works
Javascript has 'falsy' and 'truthy' values.
window.prompt('Enter an even number', '2')
This code prompts the user for a number. The result is a string (or null, if the user blanks out the prompt).
<a string or null> || '1'
If the user blanked out the prompt, it will return null. In Javascript we can use the or operator to choose between two things. null || '1' reads from left to right. The first thing is falsy so it chooses '1'.
If the user entered a number (like 10), we would get the number they entered as a string.
Then we parse the string to a number with parseInt.
Take that result and use the modulo operator % to divide by the operand and return the remainder. When you divide by 2 the remainder will either be 0 or 1. These are falsy/truthy values.
while(0) evaluates to false and breaks the loop. while(1) evaluates to true and continues the loop.
Related
Trying to output how a user inputted number compares to the number 117, very simple, yet I somehow am doing something wrong?
let output = "";
//
//input Number here
let userNumber = 117;
function calcUserNumberFunc(indvNumber) {
switch (indvNumber) {
case userNumber === 117:
return `the number ${userNumber} is equal to 117.`;
case userNumber > 117:
return `the number ${userNumber} is greater than 117.`;
case userNumber < 117:
return `the number ${userNumber} is less than 117.`;
default:
return `Invalid, or not whole number.`;
}
}
output += calcUserNumberFunc();
document.getElementById("app").innerHTML = output;
While your code is syntactically correct (ie. doesn't throw any errors), you are not using [switch][1] the way it's intended.
switch (expression) { ... } evaluates expression and matches its values with the value you provide in the cases. In your code, you are not doing anything with that parameter.
What's actually happening, is that you are comparing indvNumber against the results of your comparisons (eg. userNumber === 117) and since all of them are bools (true or false) you are basically comparing indvNumber against true or false.
That said. For your use case, you actually what to use [IFs][2] statements to compare all your cases.
Also, when you are calling the function calcUserNumberFunc() you are not passing any parameter so indvNumber is undefined which evaluates to false (as is a [falsy value][3]) that's why in your code you will always be getting the number ${userNumber} is greater than 117.;. userNumber > 117 is false and is compared against indvNumber which is undefined.
[3]https://developer.mozilla.org/en-US/docs/Glossary/Falsy
You can refactor your code to this and it will help to make the function more reusable.
//input Number here
let inputNumber = 117
// Assuming userNumber is the input Number and indvNumber is the number to be compare
function calcUserNumberFunc(userNumber, indvNumber = 117) {
if (userNumber === indvNumber) {
return `the number ${userNumber} is equal to ${indvNumber}.`;
}
if (userNumber > indvNumber) {
return `the number ${userNumber} is greater than ${indvNumber}.`;
}
if (userNumber < indvNumber) {
return `the number ${userNumber} is less than ${indvNumber}.`;
}
return `Invalid, or not whole number.`;
}
document.getElementById("app").innerHTML = calcUserNumberFun(inputNumber);
You can now pass input Number directly as userNumber parameter
Eg: calcUserNumberFunc(116) and it will return the number 116 is less than 117..
You can also overwrite 117 to different number if you ever need to change it for example comparing user input to 120 instead.
Eg: calcUserNumberFunc(120, 120). This should return the number 120 is equal to 120.
I'm learning the basics of JavaScript and am trying to write a recursive function to add together a group of integers. For example, the function argument would be 1234 and the result should be 10. Here's what I have so far...
function sumDigits(numbersStr) {
var numToString = numbersStr.toString()
var numArr = numToString.split('').map(Number);
var sum = 0;
// base case
if (numArr.length === 0) {
return sum
}
// recursive case
else {
var popped = numArr.pop();
sum+=popped;
return sumDigits(numArr);
}
}
But I get an infinite loop whenever I run this (my tab crashes). If I'm popping the last element of an array, adding it to the sum variable, then calling the function again on the shortened array, then why do I get an infinite loop? Many thanks!
The problem in your code is that sumDigits expects to get a number, but in the recursion you pass an array of numbers to it.
You could use a string or number as argument of the function and convert the value to a string.
Then check the length and return zero if the length is zero (usualy the exit condition).
If not return the value of the fist character and add the result of calling the function with a sliced string from index one.
Basically a recurisve function have two parts.
The exit condition with an exit value. This depends on the purpose of the recursive function. It is usually a neutral value, like zero for addition, or 1 for multiplication.
The actuall value plue a arithmetic operation and the call of the function again with a reduced string/array or numerical value.
function sumDigits(num) {
num = num.toString();
return num.length === 0
? 0
: +num[0] + sumDigits(num.slice(1));
}
console.log(sumDigits(1234));
Another approach would be the use of tail recursion, which does not extend the stack for each calling function, because the function ends with the call without keeping a temporary value liek in above function, the actual numerical value +num[0] and the waiting for execution of the adition.
In this case, you could store the intermediate result along with the calling of the function.
function sumDigits(num, sum) { // num is expected to be a string
sum = sum || 0;
if (num.length === 0) {
return sum;
}
return sumDigits(num.slice(1), sum + +num[0]);
}
console.log(sumDigits('1234'));
function digitCount(num) {
let val1 = num % 10
let rem = Math.floor(num / 10)
return val1 + (rem != 0 ? digitCount(rem) : 0)
}
console.log(digitCount(87))
The problem is that your function takes a number as it's argument, but when you use it recursively, you're giving it an array back. I would recommend pulling the recursive part into its own helper function like so:
function sumDigits(num) {
var numStr = num.toString()
var numArr = numStr.split('').map(Number);
function sumHelper(arr) {
// Base case:
if (arr.length === 1) {
return arr[0];
}
// Otherwise recurse (return last number plus the sum
// of the remainder):
return arr.pop() + sumHelper(arr);
}
// Then use that recursive helper:
return sumHelper(numArr);
}
console.log(sumDigits(1234))
Your function expects a string, but on the recursive call, you pass it an array.
Additionally, you've got a call to .map that isn't needed because you can convert the strings in the .split array to numbers simply by prepending a + to them.
Is there any reason you just don't use Array.reduce?
function sumDigits(stringOfNums) {
// Split the string into an array of strings. Reduce the array to the sum by
// converting each string to a number.
console.log(stringOfNums.split('').reduce(function(x,y){ return +x + +y}, 0));
}
sumDigits("1234");
Passing an array in the recursive call will guarantee that its .toString() will never be empty because the commas will add more characters than have been removed.
Instead, do it mathematically so you don't need an array or even string conversion.
function sumDigits(num) {
return num ? (num%10) + sumDigits(Math.floor(num/10)) : 0
}
console.log(sumDigits(1234))
This assumes a positive integer is passed. You'll need additional guards if other input could be provided.
There's no need to convert the number to an array. You can get the last digit of a number with number % 10, and remove that digit with Math.floor(number / 10). Then recurse until the number is 0.
function sumDigits(num) {
if (num == 0) {
return 0;
} else {
var last = num % 10;
var rest = Math.floor(num / 10);
return last + sumDigits(rest);
}
}
console.log(sumDigits(1234));
Barmar has a good voice of reason. Converting from number to string then converting back to number again is a bit silly. Plus, if this is a homework assignment, using high-level functions like String.prototype.split probably won't teach you much.
Here's a tail-recursive version Barmar's program written using functional style
base case - the input number n is zero, return the accumulator acc
inductive case - n is not zero; recur with the next n and the next acc
const sumDigits = (n = 0, acc = 0) =>
n === 0
? acc
: sumDigits (n / 10 >> 0, acc + n % 10)
console.log (sumDigits ()) // 0
console.log (sumDigits (1)) // 1
console.log (sumDigits (12)) // 3
console.log (sumDigits (123)) // 6
console.log (sumDigits (1234)) // 10
I am defining a function that takes three numbers as arguments and returns the largest of them.
Here is my code:
var instructions = alert("Choose a set of numbers to input for the computer to determine which value is the largest");
var inputOne = prompt("Please input your first desired value");
var inputTwo = prompt("Please input your second desired value");
// THIS ARRAY STORES THE VALUES OF inputOne && inputTwo
var maxInput = Math.max([inputOne, inputTwo]);
var inputThree = prompt("Please input your third desired value");
// THIS WILL COMPARE BETWEEN THE inputThree && THE MAX INPUT OF THE USERS FIRST TWO CHOICES
var maxNumber = Math.max(maxInput, inputThree);
//validate if inputs are numbers and not letters
// isNaN()
var compare = function (maxNumber, inputThree) {
if (inputThree === maxNumber) {
return alert("The result is the same!");
} else if (inputThree != maxNumber) {
return alert(maxNumber + " " + "is the larger value!");
}
}
compare(maxNumber, inputThree);
Now I'm getting a result of "NaN is the larger value!" and it's driving me crazy! I tried running console.log to see where I'm getting NaN but that didn't work at all. All that did was log NaN to the console.
I also tried taking the parameters out of Math.max( ) however was just getting:
"-infinity is the larger value!"
Can someone at least give me a hint as to why this is happening? Or explain to me further what is going on.
Math.max([inputOne, inputTwo]) should be Math.max(inputOne, inputTwo)
Why don't you just get the largest of all of them with just
var maxNumber = Math.Max(inputOne, inputTwo, inputThree);
Here:
var inputThree = prompt("Please input your third desired value");
inputThree is a String (i.e. its value has a Type of String), always. And here:
var maxNumber = Math.max(maxInput, inputThree);
maxNumber is a Number, always (because that's what Math.max returns, even though the arguments are Strings). So:
inputThree === maxNumber
is always false, because a Number is never equal to a String (see the Strict Equality Comparison Algorithm). So either convert inputThree to a Number, e.g.
+inputThree === maxNumber
or use ==.
inputThree == maxNumber
What is the best way to prevent divide by 0 in javascript that is accepting user inputs.
If there is no particular way to achieve this what would be the best way to handle such a situation so as to not prevent other scripts from executing?
Any insights are much appreciated.
There is no way to do that with the normal / and /= operators.
The best way to do what you want is with guards:
function notZero(n) {
n = +n; // Coerce to number.
if (!n) { // Matches +0, -0, NaN
throw new Error('Invalid dividend ' + n);
}
return n;
}
and then do division like
numerator / notZero(denominator)
Alternatively you can always guard the output
function dividend(numerator, denominator) {
var quotient = numerator / denominator;
if (quotient !== quotient) { throw new Error(numerator + " / " + denominator); }
return quotient;
}
but that loses the readability and expressiveness of /=.
Off the top of my head you could:
Check the user input to see if the denominator is zero (or evaluates to zero, depending on what your script actually does).
Check if the result of the action isFinite() and if not then handle appropriately.
what would be the best way to handle such a situation so as to not prevent other scripts from executing
Division by zero doesn't seem to prevent other scripts from execution in JavaScript:
var a = 20;
var b = 0;
var result = a/b;
console.log(result); // returns Infinity
If you want something different to happen in case of division by zero, you could use
function divideIfNotZero(numerator, denominator) {
if (denominator === 0 || isNaN(denominator)) {
return null;
}
else {
return numerator / denominator;
}
}
Hope this is useful
(denominator != 0 ? numerator/denominator : Infinity)
or whatever value you want to put at the end.
Greetings.
To prevent (unwanted) execution
Always verify critical user input and/or results
Use logic and/or callbacks you can prevent to execute
On HTML forms etc. you can use i.e. return false; as value to stop submission.
Why not just check if the denominator is zero?
if(x != 0) z = y / x;
You can also check if the result is Infinity:
3 / 0 == Infinity
Results in true;
(Only tested in chrome.)
A bit different than stopping execution, but the ternary operator is a pretty slick way to customize variable assignment.
var one = 1,
zero = 0,
customValue = 1;
var quotient = zero===0 ? customValue : one / zero;
This way, by setting the customVariable to the integer of your choice, you can expect a predictable result when division by zero occurs.
The best way is contextual. But here's the easiest:
function myFunction( input ){
input = 0 ? 0.0001 : input; // same as if( input == 0 ){ input = 0.0001; }
return 1 / input;
}
Basically if the input is zero, turn it into a very small number before using as a denominator. Works great for integers, since after your division you can round them back down.
A couple caveats prevent this from being universal:
It could cause false positives if your input accepts really small numbers
It won't trigger any error-handling code, if you need to do something special if zero is entered
So it's best for general-purpose, non-critical cases. For example, if you need to return the result of a complex calculation and don't care if the answer is accurate to N digits (determined by 0.0001 vs. 0.00000001, etc.); you just don't want it to break on a divide-by-zero.
As another answer suggested, you could also create a reusable global function.
function divisor( n ){ return ( n = 0 ? 0.0001 : n ); }
function myFunction( input ){ return 1 / divisor( input ); }
Possible improvements:
function divisor( n, orError ){
if( typeof n == 'undefined' || isNaN( n ) || !n ){
if( orError ){ throw new Error( 'Divide by zero.' ); }
return 0.000000000000001;
}else{ return 0 + n; }
}
This would take any value (null, number, string, object) and if invalid or zero, return the failsafe zero-like value. It would also coerce the output to a number just in case it was a string and you were doing something odd. All this would ensure that your divisor function always worked. Finally, for cases where you wanted to handle such errors yourself, you could set the second parameter to true and use a try/catch.
Set a cap on what the value for the numerator can be and set the numerator to that value when the denominator equals 0.
This is a faster approach yet is confusing
let divisor;
let dividend;
let result =(dividend/divisor) || 0
if the result for instance if you are calculating percentage is infinite you can give it 0 as value;
const progress = goal == 0 ? 0 : total/goal
First of all,
What am i doing ?
I have to set the limit of emails in our product in webpage.It's handled with the javascript for validation.It handles upto 8 digit numbers fine. But in our QA team enters the more than 17 digit number in the text box of other email field.It throw the negative message.What can i do ???
My sample code is:
if(form.otherEmails) {
if(validEmailArray.endsWith(',')){
var otherEmailLength = validEmailArray.substring(0,validEmailArray.length-1).split(",");
var setLimitOtherEmail = window.parent.document.getElementById('setLimitOtherEmail').value;
if(setLimitOtherEmail == '-1'){
form.otherEmails.value = otherEmailLength;
}
else if(otherEmailLength.length <= setLimitOtherEmail){
form.otherEmails.value = otherEmailLength;
}
else{
alert("More than "+setLimitOtherEmail+ " " +"Recipient emailIds not allowed in this section.\nIf you want to send it to more recipients, Please create a Bulk Contact Group.");
form.otherEmails.focus();
return false;
}
}
else
form.otherEmails.value = validEmailArray;
}
This is due to the limit being a string, and when a string is being compared to a number (length) the number is coerced into a string, not the other way around.
These are then compared lexicographically - and lexicographically "9" is more (>) than "19".
You need to use parseInt(setLimitOtherEmail, 10) to get the value as a number before comparing them.
Try parsing each of the numbers into Integers before performing any comparison operations on them.
var setLimitOtherEmail = parseInt(window.parent.document.getElementById('setLimitOtherEmail').value);
Other than that are you certain otherEmailLength is actually the number that you want? From the looks of it you are taking the substring of validEmail array and splitting it on "," but it doesn't look like you actually get the length of the array. Try adding .length to the end of the value of otherEmailLength.
var otherEmailLength = validEmailArray.substring(0,validEmailArray.length-1).split(",").length;