JS calculation issue - javascript

I have a simple vat calculator, but there is something funny with one of the calculation. The problem is in the last column, saying moms. e=a + d * 0.25 is correct, but the code below is not. It shows a too big number when calculating.
JS Code:
$(document).ready(function() {
$('#submit').click(function() {
//get cost and check value
var cost = $('#cost').val();
var check = $('#checkBox');
if (cost != null && cost != "") {
if (cost < 350) {
//c = a * 1
$('#total').val(cost);
$('#toll').val("");
$('#moms').val("");
} else {
if (check.is(':checked')) {
//c = a* 1.107* 1.25
$('#total').val((cost * 1.107 * 1.25).toFixed(2));
//d = a * 0.107
$('#toll').val((cost * 0.107).toFixed(2));
} else {
$('#total').val((cost * 1.25).toFixed(2));
$('#toll').val("");
$('#moms').val("");
}
if ($('#toll').val() != null && $('#toll').val() != "") {
//e = (a + d) * 0.25
var moms = (cost + $('#toll').val()) * 0.25;
$('#moms').val(moms.toFixed(2));
}
}
}
})
});

The value of input elements will always be a string. In most of your code, you're using the "cost" value in such a way that it will be implicitly converted to a number. However, the + operator is different, and will preferentially perform string concatenation to addition.
If you explicitly force the cost to be a number when you initialize it, things should work better:
var cost = +$('#cost').val();
That leading unary + operator will force the string value to be treated as a number. Now, of course, if the string doesn't look like a good number, then cost will be set to NaN, so you should check for that:
if (!isNaN(cost)) {
That can replace your current check to see if cost is not empty.
edit Sorry, you'll also need to convert the value of $('#toll').val() so that line would look like:
var moms = (cost + +$('#toll').val()) * 0.25;
The JavaScript + operator really likes strings.

Related

Why does if statement not work and make my element disappear using display: none?

I am building a tip calculator and I couldn't make the if statement in my function work it just skips to calculating.
function calculate() {
var bill = parseInt(document.getElementById("bill").value);
var tip = parseInt(document.getElementById("tip").value) * .01;
var persons = parseInt(document.getElementById("persons").value);
if (bill == "" || tip == "") {
alert("Please enter value");
return;
};
if (persons == "" || persons <= 1) {
persons = 1;
document.getElementById("perPerson").style.display = "none";
} else {
}
let totalTipPer = (bill * tip) / persons;
let totalPer = (bill + (tip * 100)) / persons;
let totalTip = bill * tip;
let total = bill + (tip * 100);
totalTipPer = totalTipPer.toFixed(2);
totalPer = totalPer.toFixed(2);
total = total.toFixed(2);
totalTip = totalTip.toFixed(2);
document.getElementById("total-tip/person").innerHTML = totalTipPer;
document.getElementById("total-price/person").innerHTML = totalPer;
document.getElementById("total-tip").innerHTML = totalTip;
document.getElementById("total-price").innerHTML = total;
}
document.getElementById("calculate").onclick = function () {
calculate();
document.getElementById('results').style.display = 'block';
}
I expect the div encapsulating Tip Amount per person and total per person and to not appear when the input value of persons is empty.
Function parseInt returns 'An integer number parsed from the given string. If the first character cannot be converted to a number, NaN is returned.'
if you rpovide an empty value ('') it will return
NaN which is not equal to anything, even itself.
there are several ways to fix this:
check if it is a NaN with Number.isNaN(var)
use an intermediate value like var personsValue and check if it is equal to empty string ''.
use Hybrid suggested solution and assign a 0
value for falsy value('', undefined, n
ull etc...)
The issue is that persons becomes NaN, since if the value is left blank, "" becomes NaN when it is run through parseInt().
The way to fix this is by defaulting it to 0 if the field is left blank.
var persons = parseInt(document.getElementById("persons").value || 0);
as others pointed out parseInt is returning NaN if the field is blank, but this will also happen if the user inputs $5.00 for example.
Here's one way to make sure the value can be converted to a number before doing so.
// This function determines if a JavaScript String can be converted into a number
function is_numeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
function calculate() {
// first put the input values into separate variables
billValue = document.getElementById("bill").value;
tipValue = document.getElementById("tip").value;
personsValue = document.getElementById("persons").value;
// use the is_numeric() function above to check if the values can be converted to numeric
if (!is_numeric(billValue) || !is_numeric(tipValue)) {
alert("Please enter values for bill and tip");
return;
}
// the rest of your code here
}
Hope this helps.

How to format numbers as percentage values in JavaScript?

Was using ExtJS for formatting numbers to percentage earlier. Now as we are not using ExtJS anymore same has to be accomplished using normal JavaScript.
Need a method that will take number and format (usually in %) and convert that number to that format.
0 -> 0.00% = 0.00%
25 -> 0.00% = 25.00%
50 -> 0.00% = 50.00%
150 -> 0.00% = 150.00%
You can use Number.toLocaleString():
var num=25;
var s = Number(num/100).toLocaleString(undefined,{style: 'percent', minimumFractionDigits:2});
console.log(s);
No '%' sign needed, output is:
25.00%
See documentation for toLocaleString() for more options for the format object parameter.
Here is what you need.
var x=150;
console.log(parseFloat(x).toFixed(2)+"%");
x=0;
console.log(parseFloat(x).toFixed(2)+"%");
x=10
console.log(parseFloat(x).toFixed(2)+"%");
Modern JS:
For any of these, remove * 100 if you start with a whole number instead of decimal.
Basic
const displayPercent = (percent) => `${(percent * 100).toFixed(2)}%`;
Dynamic with safe handling for undefined values
const displayPercent = (percent, fallback, digits = 2) =>
(percent === null || percent === undefined) ? fallback : `${(percent * 100).toFixed(digits)}%`;
Typescript:
const displayPercent = (percent: number) => `${(percent * 100).toFixed(2)}%`;
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
function myFunction(num) {
number = num.toString();;
console.log(number)
var words2 = number.split(".");
for (var i = 0; i < words2.length; i++) {
words2[i] += " ";
}
num1 = words2[0];
num2 = words2[1];
num1 = num1.trim();
if(num2==undefined){
number1 = num1+'.00%';
return number1;
}else{
num2 = num2.trim();
number1 = num1+'.'+num2+'%';
return number1;
}
}
document.getElementById("demo").innerHTML = myFunction(50.12);
</script>
</body>
</html>
I had decimal values such as 0.01235 and 0.016858542 that I wanted to convert to percentages 1.235% and 1.6858542% respectively. I thought it was going to be easy, just calculate (0.012858542 * 100) and I'm good to go. I was wrong, (0.012858542 * 100) = 1.2858542000000002 because of decimal conversion.
Let's add toFixed() to the calculation and I end up with the right value.
(0.012858542*100).toFixed(7) // returns "1.2858542"
(0.01235*100).toFixed(7) // returns "1.2350000"
I don't like to show four trailing zeros when they're unnecessary. One solution I thought about was to use replace() to remove all trailing zeros but I ended up using Numeral.js instead because it does all the work for me while it's lightweight. I can recommend it!
import numeral from 'numeral';
numeral(0.012858542 * 100).format('0.00[0000]') // returns "1.2858542"
numeral(0.01235 * 100).format('0.00[0000]') // returns "1.235"
Transform number to percentage with X float decimal positions
function toPercent(number, float) {
var percent = parseFloat(number * 100).toFixed(float) + "%";
return percent;
}

Generating Two Numbers With a Specific Sum

I'm trying to generate two numbers with a specific sum. Here is my proposed method:
Edited: http://jsfiddle.net/KDmwn/274/
$(document).ready(function () {
function GenerateRandomNumber() {
var min = -13, max = 13;
var random = Math.floor(Math.random() * (max - min + 1)) + min;
return random;
}
var x = GenerateRandomNumber();
function GenerateRandomNumber2() {
var min2 = -13, max2 = 13;
var random2 = Math.floor(Math.random() * (max2 - min2 + 1)) + min2;
if ((random2 + x) == 0){
return random2};
}
var xx = GenerateRandomNumber2();
There's something wrong with the if ((random2 + x) = 0) line, as the code runs perfectly fine when it's removed. How can I modify this line so that the sum of the two numbers is 0? It would be most helpful if someone could modify the Jsfiddle that I've included. Thanks!
This is invalid:
if ((random2 + x) = 0){
You cannot assign something to an expression.
You probably meant to use the comparison operator (==), like this:
if ((random2 + x) == 0){
Are you trying to make it only output a second number that, when added to the first, equals 0? Because it actually already does that - but only if it gets it on the first try (try hitting refresh at least 30 times.) You need to tell it to keep re-choosing (looping) the second random number while the sum isn't 0:
function GenerateRandomNumber2() {
var min2 = -13,
max2 = 13;
var random2;
while ((random2 + x) !== 0) {
random2 = Math.floor(Math.random() * (max2 - min2 + 1)) + min2;
}
return random2;
}
http://jsfiddle.net/vL77hjp0/
To take this one step further, if I'm reading this right (if not ignore this) it looks like you might want to eventually choose a random sum and have it determine the required second number to be added. To do this, we would replace the 0 in our "while" loop with 'sum'. And 'sum' would have to be defined as a random number with a "max=x+13" and "min=x-13" (otherwise the random number may be too high/low for random2 to ever reach, causing the browser to crash.) [Or just remove the limits from random2.]
http://jsfiddle.net/fkuo54hc/
First, your GenerateRandomNumbers2 function returns undefined value other than in your if statement. So you need to return a value. I updated your fiddle and refactor some of your code.

JS Variable is outputting as isNaN when I need a number

Here is the assignment so it's clear what I'm trying to do.
Write a program that calculates the price of a hotel room based on three factors. First, how many will be in one room: 1-2, 3-4, or 5-6? No more than six are allowed in a room. Second, are the guests members of AAA? Third, do they want a room with a view? The rate is calculated as follows:
Basic room rate is:
1-2 people = $50/night
3-4 people = $60/night
5-6 people = $70/night
There is a discount for AAA members off of the basic room rate per night:
1-2 people = 15%
3-4 people = 10%
5-6 people = 5%
A room with a view costs 10% more per night after all other calculations are performed.
The program should prompt the user for all the inputs, perform the calculations and output the total cost per night. It is suggested to use at least some nested if/else structures to calculate the cost.
Debuggers like firebug and JSLint haven't been any help and I suspect I'm just doing something completely wrong, though I haven't had trouble with "nested if" logic assignments before. Regardless I am a complete and utter newby.
When I test by inputting 1 for numberOfGuests, N for tripleAStatus, and N for roomView, finalRate is returning as isNaN (I know this means not a number), and I can't figure out why.
//Variable Declaration
var numberOfPeople;
var tripleAStatus;
var roomView;
var discountRate;
var roomRate;
var finalRate;
var discountPercent;
//Input
numberOfPeople = prompt("How many guests will their be? 6 Maximum.");
tripleAStatus = prompt("Are you a AAA Member? Y/N.");
roomView = prompt("Would you like your room to have a view?");
//Logic
if ((numberOfPeople <= 2) && (numberOfPeople > 0)) {
roomRate = 50;
discountPercent = .15;
} else if ((numberOfPeople <= 4) && (numberOfPeople > 2)) {
roomRate = 60;
discountPercent = .10;
} else if ((numberOfPeople <= 5) && (numberOfPeople > 4)) {
roomRate = 70;
discountPercent = .5;
} else {
alert("Your number of guests must be at least 1 and no more than 6");
}
if (tripleAStatus = "Y") {
discountRate = roomRate - (roomRate * discountRate);
} else if (tripleAStatus = "N") {
discountRate = roomRate;
} else {
alert("You need to answer with either Y or N");
}
if (roomView = "Y") {
finalRate = (discountRate) + ((discountRate) * .10);
} else if (roomView = "N") {
finalRate = discountRate;
} else {
alert("You need to answer with either Y or N");
}
//Output
document.write("Total cost per night is " + "$" + finalRate);
It looks like
discountRate = roomRate - (roomRate * discountRate);
Should read
discountRate = roomRate - (roomRate * discountPercent);
Which is why you're getting NaN in finalRate; discountRate hasn't been defined at this point, so your code actually reads discountRate = 1 - (1 * undefined).
As other posters have mentioned, you also need to change your conditionals to use == or ===; = is an assignment operator, so rather than checking if tripleAStatus is "Y", you're actually checking if "Y" evaluates to true (which it always will).
tripleAStatus = 'N';
if (tripleAStatus = 'Y') {
// tripleAStatus is now "Y", and the code inside this if will always be executed
}
Working changes: http://jsfiddle.net/5ZVkE/
In your If statements, you are assigning values by using single "=". Since the assignment always occurs, it will return true. In order to compare values, you need to use double "==" in the if statement. like this:
if (tripleAStatus == "Y") {
discountRate = roomRate - (roomRate * discountRate);
} else if (tripleAStatus == "N") {
discountRate = roomRate;
} else {
alert("You need to answer with either Y or N");
}
Replace the single '=' in your 'if' statements with '=='. You're currently using assignment operators instead of equality.
e.g.:
if (tripleAStatus == "Y") ...
You are using assignments instead of equality operators in your if statements. i.e. change
if (tripleAStatus = "Y")
to
if (tripleAStatus == "Y")
Please use ===!! this way, the type in the statement isn't casted and therefor more strictly checked if its the same type.
if (tripleAStatus === "Y") {
discountRate = roomRate - roomRate * discountRate;
} else if (tripleAStatus === "N") {
discountRate = roomRate;
}
/e -> & its faster!
prompt() returns a STRING not a NUMBER.
Use parseInt() with numberOfPeople.
And the other problem, you copied and pasted the wrong variable names in your formulas. Look at how you are using discountRate instead of discountPercent.

Excel PMT function in JS

I found i little snipet on internet, about PMT calculate.
function PMT(i, n, p) {
return i * p * Math.pow((1 + i), n) / (1 - Math.pow((1 + i), n));
}
function CalculatePMTFromForm(idLoanAmount, idAnnualInterestRate, idMonths, idResult) {
var i = jQuery('#' + idAnnualInterestRate).val() / 1200;
var n = jQuery('#' + idMonths).val();
var p = jQuery('#' + idLoanAmount).val();
var pmt = PMT(i, n, -p);
jQuery('#' + idResult).val(pmt.toFixed(2));
}
function performCalc() {
CalculatePMTFromForm('LoanAmount', 'InterestRate', 'Months', 'Payment');
}
jQuery(document).ready(function() { performCalc(); jQuery('.calc').keyup(performCalc); });
When the page is load, in the result input box I see "NaN" , and when i tpye some irrelevant number then "-Infinity" msg appear.
I search to "NaN" in files and i found in jquery.js, but after I modify, nothing change. And I can't find Infinity
How can I change this messages?
Edit
Calling code:-
function performCalc() {
CalculatePMTFromForm('LoanAmount', 'InterestRate', 'Months', 'Payment');
}
jQuery(document).ready(function() {
performCalc(); jQuery('.calc').keyup(performCalc);
});
This is worked for me:
if(pmt>0 && pmt<Number.MAX_VALUE) {jQuery('#' + idResult).val(pmt.toFixed(2));}
This question's been dead for over a year, but I recently needed to do the same thing. Here's what I came up with:
function pmt(rate_per_period, number_of_payments, present_value, future_value, type){
if(rate_per_period != 0.0){
// Interest rate exists
var q = Math.pow(1 + rate_per_period, number_of_payments);
return -(rate_per_period * (future_value + (q * present_value))) / ((-1 + q) * (1 + rate_per_period * (type)));
} else if(number_of_payments != 0.0){
// No interest rate, but number of payments exists
return -(future_value + present_value) / number_of_payments;
}
return 0;
}
type needs to be 1 or 0, same as Excel's. The rate_per_period needs to be a decimal (eg: 0.25, not 25%).
An example:
/* Example: */
var interest = 0.07, // Annual interest
years = 5, // Lifetime of loan (in years)
present = 10000, // Present value of loan
future = 20000, // Future value of loan
beginning = 1; // Calculated at start of each period
var payment = -pmt(interest / 12, // Annual interest into months
years * 12, // Total months for life of loan
present,
future,
beginning);
And the payment for the example period (month) is ~$474.60.
Note the negation of the result, as the amount is a dedection - ie: costs you $474 - the result is a negative value. Were the result to be a credit, the result would be a positive. Generally you'll want to keep it as a negative/positive, but if you were displaying it in a format like Total Debt: $XYZ, you'd want to convert it to a positive.
NaN means "Not A Number".
Make sure you check for each input value whether it is numeric. Throw an error message if one is not, or set it to 0, depending on whether it's essential to your calculation or not.
A good collection of the best ways to check a value for whether it's numeric is this SO question:
Validate numbers in JavaScript - IsNumeric()
Try it like this:-
function CalculatePMTFromForm(idLoanAmount, idAnnualInterestRate, idMonths, idResult) {
var i = parseFloat($('#' + idAnnualInterestRate).val()) / 1200;
var n = parseFloat($('#' + idMonths).val());
var p = parseFloat($('#' + idLoanAmount).val());
var pmt = PMT(i, n, -p);
$('#' + idResult).val(pmt.toFixed(2));
}
The .val() is likely returning a string type not a number type.

Categories

Resources