How to fix infinite while loop and create functions - javascript

I am trying to make a paycheck program, that utilizes functions and while loops.
In this program, I have to create two functions, one for validating the pay rate and hours, and then one for the calculations.
In addition, I have to have the first function pass the hours and pay rate to the calculation function, and then pass it back to the first function. When I try to run the program with the first function, it seems that if I enter a pay amount under 7.25, it enters an infinite loop.
Here is the code
<script>
function payValidate(x)
{
if(isNaN(payRate) || payRate < 7.25 || payRate > 20)
{
return false;
}
else
{
return true;
}
}
function hoursValidate(x)
{
if(isNaN(hours) || hours < 1 || hours > 60)
{
return false;
}
else
{
return true;
}
}
var grossPay;
var withHolding;
var netPay;
var message;
var payRate = parseInt(prompt("Enter pay rate"));
var payRateOK = payValidate(payRate);
while(!payRateOK)
{
payRate = parseInt(prompt("Invalid pay rate. Enter pay rate again"));
payRateOk = payValidate(payRate);
}
var hours = parseFloat(prompt("Enter hours worked"));
var hoursOK = hoursValidate(hours);
while(!hoursOK)
{
hours = parseFloat(prompt("Invalid hours. Enter hours again"));
hoursOK = hoursValidate(hours);
}
grossPay = payRate * hours;
if(grossPay <= 300)
{
withHolding = grossPay * 0.10;
}
else
{
withHolding = grossPay * 0.12;
}
netPay = grossPay - withHolding;
var message = "Pay Rate: $" + payRate.toFixed(2) +
"\nHours Worked: " + hours +
"\nGross Pay $" + grossPay.toFixed(2) +
"\nWithholding $" + withHolding.toFixed(2) +
"\nNet Pay $" + netPay.toFixed(2);
alert(message);
</script>

You're creating a new variable payRateOk (notice the lower case k) instead of writing to payRateOK, the variable you check in the while loop. So payRateOK will never change, and the loop will execute infinitely.

var payRateOK = payValidate(payRate); // In here you have used "payRateOK"
while(!payRateOK)
{
payRate = parseInt(prompt("Invalid pay rate. Enter pay rate again"));
payRateOk = payValidate(payRate); // In here you have used "payRateok"
}
payRateOK != payRateOk there for you have to use same name for that
other thing is payRate is a float variable. you should use var payRate = parseFloat instead of var payRate = parseInt.
you have used hours as int type there for var hours = parseFloat should be var hours = parseInt

Related

How do I take inputs through HTML and then use those to run a loop with javascript?

I am trying to write a code which will calculate compound interest earned on an investment and after each year (i) ends, it will ask the user if they would like to continue staying invested or if they would like to cash out.
I have been able to write a for loop for calculating final payment after 10 years. However, I can't seem to figure out how to break the loop after each year ends and then ask the user a simple yes or no question about their investment preference. This is the code I input to calculate interest:
let userInput = false;
let principal = 100000;
let rate = 0.05;
let amount;
for(let year = 1; year <= 10; ++year)
{
if(userInput) {
amount = principal * Math.pow(1.0 + rate, year);
console.log(year);
console.log(amount.toFixed(2));
}
else {
{break;}
}
}
I am guessing I'll need to create a form with HTML as well, to get the input but not sure how to then take that input and add it into my java code.
I calculated compound interest but can't seem to break the loop and ask the user for go ahead after each year ends.
Here is a pure JavaScript solution without HTML (open your console log to view the output for each year):
function calculateInterest(principal, rate, time) {
let amount = principal * Math.pow(1 + (rate/100), time);
let interest = amount - principal;
return interest;
}
let principal = parseFloat(prompt("Enter the initial investment amount:"));
let rate = parseFloat(prompt("Enter the interest rate (% per year):"));
let time = 10;
let invested = true;
for (let i = 1; i <= time; i++) {
if (!invested) {
break;
}
let interest = calculateInterest(principal, rate, i);
console.log(`Year ${i}: $${interest + principal}`);
if (i < time) {
let decision = prompt("Do you want to continue staying invested? (Enter 'yes' or 'no'):");
if (decision === "no") {
invested = false;
console.log("You have chosen to cash out. Your final investment amount is $" + (interest + principal));
}
}
}
if (invested) {
console.log("You have stayed invested for 10 years. Your final investment amount is $" + (principal * Math.pow(1 + (rate/100), time)));
}
Here is an HTML and JavaScript solution:
function calculateInterest(principal, rate, time) {
let amount = principal * Math.pow(1 + (rate/100), time);
let interest = amount - principal;
return interest;
}
function calculateAndDisplay() {
let principal = parseFloat(document.getElementById("principal").value);
let rate = parseFloat(document.getElementById("rate").value);
let time = 10;
let invested = true;
for (let i = 1; i <= time; i++) {
if (!invested) {
break;
}
let interest = calculateInterest(principal, rate, i);
console.log(`Year ${i}: $${interest + principal}`);
if (i < time) {
let decision = prompt(`Year ${i} is up. Do you want to continue staying invested or cash out? Type 'continue' to stay invested or 'cash out' to end investment.`);
if (decision === "cash out") {
invested = false;
console.log("You have chosen to cash out. Your final investment amount is $" + (interest + principal));
}
}
}
if (invested) {
console.log("You have stayed invested for 10 years. Your final investment amount is $" + (principal * Math.pow(1 + (rate/100), time)));
}
}
<label for="principal">Enter the initial investment amount:</label>
<input type="text" id="principal"><br><br>
<label for="rate">Enter the interest rate (% per year):</label>
<input type="text" id="rate"><br><br>
<button onclick="calculateAndDisplay()">Calculate</button>
You can solve this in multiple ways, of which I'll demonstrate some, in simplified examples.
You can use promises (and async/await) to keep using a for-loop:
const divOptions = document.getElementById("investment-options");
const buttonStayIn = document.getElementById("stay-in");
const buttonCashOut = document.getElementById("cash-out");
const output = document.querySelector("output");
invest();
async function invest() {
let year = 0;
for (; year < 10 && await getAnswer() === "Stay in"; ++year) {
// TODO: Calculate
output.textContent = `Year ${year + 1}`;
}
divOptions.style.display = "none";
output.textContent = `You cashed out after ${year} year(s).`;
}
function getAnswer() {
return new Promise(resolve => {
// Use handlers for one(!) answer; resolve accordingly
let stayInHandler, cashOutHandler;
const removeListeners = function() {
buttonStayIn.removeEventListener("click", stayInHandler);
buttonCashOut.removeEventListener("click", cashOutHandler);
};
stayInHandler = () => {
removeListeners();
resolve("Stay in");
};
cashOutHandler = () => {
removeListeners();
resolve("Cash out");
};
buttonStayIn.addEventListener("click", stayInHandler, false);
buttonCashOut.addEventListener("click", cashOutHandler, false);
});
}
<div id="investment-options">
<button id="stay-in">Stay invested</button>
<button id="cash-out">Cash out</button>
</div>
<output>Year 0</output>
Or –instead of a for-loop– you can manually iterate per each "staying invested" click:
const divOptions = document.getElementById("investment-options");
const buttonStayIn = document.getElementById("stay-in");
const buttonCashOut = document.getElementById("cash-out");
const output = document.querySelector("output");
let year = 0;
buttonStayIn.addEventListener("click", () => {
nextYear();
if (year >= 10) {
stopInvestment();
}
});
buttonCashOut.addEventListener("click", stopInvestment);
function nextYear() {
// TODO: Calculate
++year;
output.textContent = `Year ${year}`;
}
function stopInvestment() {
divOptions.style.display = "none";
output.textContent = `You stopped your investment after ${year} year(s).`;
}
<div id="investment-options">
<button id="stay-in">Stay invested</button>
<button id="cash-out">Cash out</button>
</div>
<output>Year 0</output>
Or you can use user prompts (similar to this answer!) since they halt the site (and therefore the script) until they return:
const output = document.querySelector("output");
let year = 0;
for (; year < 10 && confirm(`Stay in? Current year: ${year}`); ++year) {
// TODO: Calculate
output.textContent = `Year ${year}`;
}
output.textContent = `You stopped your investment after ${year} year(s).`;
<output>Year 0</output>
Sidenote: User prompts (such as alert(), prompt() and confirm()) usually halt a site. This means the site will be unresponsive, and even animations will stop for the prompt's duration, resulting in bad UX.
Alternatively, you can just ask ahead of time (if possible) how many years they would like to invest:
const form = document.querySelector("form");
const output = document.querySelector("output");
form.addEventListener("submit", evt => {
evt.preventDefault();
const years = form.years.valueAsNumber;
for (let i = 0; i < years; ++i) {
// TODO: Calculate
}
form.style.display = "none";
output.textContent = `You cashed out after ${years} year(s).`;
});
<form id="f-investment">
<label for="i-years">
Invest for years:
<input id="i-years" name="years" type=number value=0 min=0 max=10>
</label>
<button>Invest</button>
</form>
<output for="f-investment"></output>
Personally, I would consider the following a malformed for-loop:
for (let i = 0; i < 10; ++i) {
if (bool) {
// ...
} else {
break;
}
}
Because it can easily be rewritten as:
for (let i = 0; i < 10 && bool; ++i) {
// ...
}

Page displays formula rather than result (but for only ONE of the cases)

I'm a student currently learning JavaScript. As practice, I wanted to make a cute reading randomizer for a friend with a simple form and a if else input validation process.
Both of my first two cases function as I expect them two, but the third, the one that actually does the calculation, does not send the result of the calculation to be displayed, but rather the formula. I'm not sure where I went wrong.
function pickfic() {
// Get the value of the input fields
let minNumChosen = document.getElementById('minNum').value;
let maxNumChosen = document.getElementById('maxNum').value;
// If input Not a Number or min bigger than max
let reply;
if (isNaN(minNumChosen) || isNaN(maxNumChosen) || minNumChosen > maxNumChosen ) {
reply = "I think you pissed off my sandwich. Also, those numbers make no sense to me.";
}
// If min is zero
else if (minNumChosen == 0) {
reply = "Really, dude? You have an Excel line for 'zero'?? Witch.";
}
else {
// if range is correct, randomize number
const generateRandomNumber = (minNumChosen, maxNumChosen) => {
return Math.floor(Math.random() * (max - min) + min);
};
reply = "Today, you should read fic number " + generateRandomNumber + "!";
}
document.getElementById("result").innerHTML = reply;
}
For the last case, the page displays : "Today, you should read fic number (minNumChosen, maxNumChosen) => { return Math.floor(Math.random() * (max - min) + min); }!"
You can find the codepen here.
EDIT: Turns out I found another bug, which is probably logic based. It seems that for my function, 2 is greater than 10. So it must be judging by the first digit...
function pickfic() {
// Get the value of the input fields
let minNumChosen = document.getElementById('minNum').value;
let maxNumChosen = document.getElementById('maxNum').value;
// If input Not a Number or min bigger than max
let reply;
if (isNaN(minNumChosen) || isNaN(maxNumChosen) || minNumChosen > maxNumChosen ) {
reply = "I think you pissed off my sandwich. Also, those numbers make no sense to me.";
}
// If min is zero
else if (minNumChosen == 0) {
reply = "Really, dude? You have an Excel line for 'zero'?? Witch.";
}
else {
// if range is correct, randomize number
const generateRandomNumber = (min, max) => {
return Math.floor(Math.random() * (max - min) + min);
};
reply = "Today, you should read fic number " + generateRandomNumber(parseInt(minNumChosen), parseInt(maxNumChosen)) + "!";
}
document.getElementById("result").innerHTML = reply;
}
<input id="minNum" placeholder="min">
<input id="maxNum" placeholder="max">
<div id="result"></div>
<button onclick=pickfic()>Click</button>
You had to add parenthesis to generateRandomNumber()
And also make the minNumChosen and maxNumChosen into integers with parseInt().
There was also another mistake where you didn't name the parameters of your generateRandomNumber function (min, max).
function pickfic() {
// Get the value of the input fields
let minNumChosen = document.getElementById('minNum').value;
let maxNumChosen = document.getElementById('maxNum').value;
// If input Not a Number or min bigger than max
let reply;
if (isNaN(minNumChosen) || isNaN(maxNumChosen) || minNumChosen > maxNumChosen ) {
reply = "I think you pissed off my sandwich. Also, those numbers make no sense to me.";
}
// If min is zero
else if (minNumChosen == 0) {
reply = "Really, dude? You have an Excel line for 'zero'?? Witch.";
}
else {
// if range is correct, randomize number
const generateRandomNumber = Math.floor(Math.random() * (maxNumChosen - minNumChosen) + minNumChosen);
reply = "Today, you should read fic number " + generateRandomNumber + "!";
}
document.getElementById("result").innerHTML = reply;
OR
You created a function which takes in values but you didn't provide the min and max value while calling the generateRandomNumber function
function pickfic() {
// Get the value of the input fields
let minNumChosen = document.getElementById('minNum').value;
let maxNumChosen = document.getElementById('maxNum').value;
// If input Not a Number or min bigger than max
let reply;
if (isNaN(minNumChosen) || isNaN(maxNumChosen) || minNumChosen > maxNumChosen ) {
reply = "I think you pissed off my sandwich. Also, those numbers make no sense to me.";
}
// If min is zero
else if (minNumChosen == 0) {
reply = "Really, dude? You have an Excel line for 'zero'?? Witch.";
}
else {
// if range is correct, randomize number
const generateRandomNumber = (min,max) => {
return Math.floor(Math.random() * (max - min) + min);
};
reply = "Today, you should read fic number " + generateRandomNumber(minNumChosen, maxNumChosen) + "!";
}
document.getElementById("result").innerHTML = reply;
}
I figured out the last bug thanks to #SchokokuchenBäcker's input on the first issue.
My conditional was comparing strings, which is why 20 was smaller than 5 !
Writing the first conditional like this:
if (isNaN(minNumChosen) || isNaN(maxNumChosen) || parseInt(minNumChosen) >= parseInt(maxNumChosen) )
makes it functional!

What is the statement i need next to determine my output given a total?

I'm quite new to JavaScript so apologies in advanced, but I'm wanting too learn!
In my html form I am asking the customer for 3 numbers (number 1,2,3) and then in my JavaScript I am calculating the total of all of them. I need to work out my next bit of code so I can:
Given the total of the numbers give I can print out to the customer you're item is free (less than 180) or it has a cost (more than 180)
Given the number is under or over a certain amount return an error message
Where would be the best place to go with this ?
function Calculate() {
var number1 = document.getElementById("number1").value;
var number2 = document.getElementById("number2").value;
var number3 = document.getElementById("number3").value;
// var totalOfNumbers = Number(number1) + Number(number2) + Number(number3);
document.getElementById("total").innerHTML = Number(number1) + Number(number2) + Number(number3);
}
You need to use an if construct.
The code would be :-
function Calculate() {
var number1 = document.getElementById("number1").value;
var number2 = document.getElementById("number2").value;
var number3 = document.getElementById("number3").value;
// use parseInt instead of Number()
var totalOfNumbers =
parseInt(number1) + parseInt(number2) + parseInt(number3);
// string message to be displayed
var message = "";
// enter you own values
var minAmount = 0;
var maxAmount = 1000;
// checking if total of the numbers is under or over a certain amount;
// if it is, then showing an error message.
if (totalOfNumbers < minAmount || totalOfNumbers > maxAmount) {
message = "Error! Please enter valid amounts."
}
// Checking if total of the numbers is under 180;
// if it is, then displaying the item is free.
else if (totalOfNumbers < 180) {
message = "You're item is free!";
}
// Checking if total of the numbers is greater than or equal to 180;
// if it is, then displaying the item is not free, and its cost.
else {
message = "You're item is not free. It has a cost of $" + totalOfNumbers;
}
document.getElementById("total").innerHTML = message;
}

Trying to get timer to start once arrived on the page

I made the following fiddle of what I have right now..
https://jsfiddle.net/r5yj99bs/1/
I'm trying to start right when I get onto a page, but allowing the option to leave the pause/resume option. Then is there anyway to display the remaining time as '5 minutes' instead of '300 seconds' and then count down that way rather than only seconds.
<button class="start-pause">Start</button>
<h2 class="time-left"></h2>
var times = [];
var counter_interval;
var $time_left = $('.time-left');
var $button = $('.start-pause');
// timer length in seconds
var timer_length = 300;
$('body').on('click', '.start-pause', function() {
// are we starting or stopping?
var starting = times.length % 2 == 0;
times.push(Date.now());
if (starting) {
$button.html('Pause');
counter_interval = setInterval(function() {
var time_left = Math.floor(timer_length - sum_elapsed());
if (time_left < 1) {
clearInterval(counter_interval);
return finished();
}
$time_left.html(time_left);
}, 100);
} else {
$button.html('Resume');
clearInterval(counter_interval);
}
});
var sum_elapsed = function() {
sum = 0;
for (var i=0; i<times.length; i++) {
if (i % 2 == 1) {
sum += (times[i] - times[i-1]);
}
if (i == (times.length - 1)) {
sum += (Date.now() - times[i]);
}
}
// convert milliseconds to seconds
return sum / 1000;
};
var finished = function() {
$button.attr('disabled','disabled').html('Finished');
$time_left.html("Time's Up");
};
There is a good time module called moment. You can get it through npm or from moments.com
That can format relative time to human readable strings.
If you want to do it yourself, take the seconds modulus 60 to get the minutes. Using modulus you can extract all info about hours and so on.
You may change the following line:
$time_left.html(time_left);
to:
$time_left.html(secToMinTxt(time_left));
and add the following functions:
function pad(num) {
var str = "" + num;
var pad = "00";
return pad.substring(0, pad.length - str.length) + str;
}
function secToMinTxt(seconds) {
var min = Math.floor(seconds / 60);
var sec = seconds % 60;
return pad(min) + ":" + pad(sec);
}
JSFiddle reference : https://jsfiddle.net/r5yj99bs/2/
If interpret Question correctly, try using Math.round with argument existing time_left variable divided by 60
var time_left = Math.round(Math.floor(timer_length - sum_elapsed()) / 60);
jsfiddle https://jsfiddle.net/r5yj99bs/3/

Calculating investment values with javascript

I am currently learning javascript. I have created a calculator to find invesment future value. It is giving me an incorrect value when it displays the future value. I have checked the formula several times but it still gives me an error. Also, I have set alerts to appear if the interest is less than 0 or greater than 20 but nothing is showing. How would i be able to properly display the correct future value and alerts when necessary? Example
Javascript
var $ = function (id) {
return document.getElementById(id);
}
var calculate_click = function () {
var investment = parseFloat( $("investment").value );
var annualRate = parseFloat( $("rate").value ) /100;
var years = parseInt( $("years").value );
$("futureValue").value = "";
if (isNaN(investment) || investment <= 0) {
alert("Investment must be a valid number\nand greater than zero.");
} else if(isNaN(annualRate) || annualRate <= 0 || annualRate > 20) {
alert("Annual rate must be a valid number\nand less than or equal to 20.");
} else if(isNaN(years) || years <= 0 || years > 50) {
alert("Years must be a valid number\nand less than or equal to 50.");
} else {
//var monthlyRate = annualRate / 12;
//var months = years * 12;
var futureValue = 0;
for ( i = 1; i <= years; i++ ) {
futureValue = ( futureValue + investment ) *
( 1 + annualRate );
}
$("futureValue").value = futureValue.toFixed(2);
}
}
var clear_click = function () {
$("investment").value = "";
$("rate").value = "";
$("years").value = "";
$("futureValue").value = "";
}
window.onload = function () {
$("calculate").onclick = calculate_click;
$("investment").focus();
$("clear").onclick = clear_click;
}
Using .value is incorrect, its javascript, while this is jquery, try adding a # in front and use .val() instead.
Its similar to this:
jquery function val() is not equivalent to "$(this).value="?
EDIT
He's not using jquery, ignore this.
If I remember the future value correctly, you are messing up the formula, which is why you aren't getting the expected value.
Change:
for ( i = 1; i <= years; i++ ) {
futureValue = ( futureValue + investment ) *
( 1 + annualRate );
}
To:
futureValue = investment*Math.pow((1+annualRate), years);
Not quite sure why you are looping through each year, but it should be based on powers to the number of years (again, if I remember correctly)
// to calculate the increase in production for each month
function getPlan(startProduction, numberOfMonths, percent) { // the function is declared
let Goals = []; //Goals is assigned
let currentProduction=startProduction; //declaring the currentProduction by assigning the value of startProduction
for(let i=0; i<numberOfMonths;i++){ //for each month, increase the currentProduction by the percentage interest = Math.floor(currentProduction+(currentProduction*(percent/100)));
currentProduction= interest;
//after each iteration, assign the new currentProduction
Goals.push(Math.floor(currentProduction));
//adding the currentprodcution of each months to the Goals
} return Goals; } console.log(getPlan(2000,6,67));
Output:
[ 3340, 5577, 9313, 15552, 25971, 43371 ]

Categories

Resources