Making math solver...NaN message - javascript

I am trying to make a simple quadratic formula solver for my own personal use. It works for the most part, but there's one problem: it only works when the answers are Rational numbers (i.e., it won't display sqrt(-1) because that's "i"). When it tries to perform the calculation and the answer isn't a rational, it will display "NaN". My code looks like this:
...*regular html*
<script type = "text/javascript">
var aValue = prompt("What is your 'a' value?");
var bValue = prompt("What's your 'b' value?");
var cValue = prompt("What's your 'c' value?");
var quadFinder = function x_finder(a,b,c) {
document.write((-1 * b + Math.sqrt(b*b - 4*a*c)) / 2*a);
document.write("<br>");
document.write((-1 * b - Math.sqrt(b*b - 4*a*c)) / 2*a);
};
quadFinder(aValue,bValue,cValue)
I know the function is all sound because it will work as long as the answer is only a number.
One other question: what is the Math. command that will round the number? I once put in a few numbers and it came out to some crazy number with around 10 decimal numbers after it.

You might try looking at the discriminant and catching complex cases:
var quadFinder = function x_finder(a,b,c) {
var disc = b * b - 4 * a * c;
if (disc >= 0){
document.write((-1 * b + Math.sqrt(b*b - 4*a*c)) / 2*a);
document.write("<br>");
document.write((-1 * b - Math.sqrt(b*b - 4*a*c)) / 2*a);
} else {
var real = (-1 * b) / (2 * a);
var complex = Math.sqrt(-disc)/(2 * a);
document.write(real + " + " + complex + "i");
document.write("<br>");
document.write(real + " - " + complex + "i");
};

Related

Is there any problem with converting this excel formula to javascript?

Here is the excel formula:
=E2-(J2*2*G2)-(K2*E2*2)/30+IF((L2+M2)>60,((L2+M2)-60)*H2+60*G2,(L2+M2)*G2)+(N2/$AE$1)*$AE$2+(Q2*$AE$5+P2*$AE$4+O2*$AE$3)
Here what I tried (Javascript):
var E2 = $("#sentence").val();
var J2 = $("#deduction").val();
var G2 = 55145;
var K2 = $("#absence").val();
var L2 = $("#overtime").val();
var M2 = 0;
var H2 = 50050;
var N2 = $("#transportation").val();
var sixty;
if ((L2 + M2) > 60) {
sixty = ((L2 + M2) - 60) * H2 + 60 * G2;
} else {
sixty = (L2 + M2) * G2;
};
var result = E2 - (J2 * 2 * G2) - (K2 * E2 * 2) / 30 + sixty;
I couldn't find the way to conver this part of formula:
+(N2/$AE$1)*$AE$2+(Q2*$AE$5+P2*$AE$4+O2*$AE$3)
Here I found the problem:
Even if one of the variables sets to null, then the formula does not work properly.
It looks like some pretty basic math.
let total = (N2 / AE1) * AE2 + (Q2 * AE5 + P2 * AE4 + O2 * AE3 )
This is basically impossible to translate without seeing the actual spreadsheet but that should get you started. Also, make sure to take into consideration order of operations because the computer is going to evaluate it from left to right unless there are parenthesis (where it will evaluate those first).

Round all numbers in the string

I've got formula strings like:
let a = '554898128.3227372 + (-1.35880 * (A * 12)) + (1.1171758319197438 * (B * 13)) + (0.8813173184360715 * (x + 1))';
or
let b = '10867.306445101707 + (1.6367961676820935 * (X + 1))';
I want to round numbers in the formula to three decimals. What's the fastest way to do that? I thought about using a.split(' '); to split my string to array and checking if it's number, but what do I do about the round brackets? The formula has to remain the same just with rounded values afterwards
A crude way to do that would be to extract everything that looks like a number and apply toFixed.
let a = '554898128.3227372 + (-1.35880 * (A * 12)) + (1.1171758319197438 * (B * 13)) + (0.8813173184360715 * (x + 1))';
a = a.replace(/-?\d+(\.\d+)?/g, n => Number(n).toFixed(3))
console.log(a)
A better, but far more complicated, option is to parse the string and replace the numbers in the parse tree. Since I presume you're going to need this anyways, to evaluate the formula, this might be actually the way to go.
I'd use a regular expression to match numeric characters with decimals, capturing everything up to the first 3 decimals, and replace with that captured group:
let a = '554898128.3227372 + (-1.35880 * (A * 12)) + (1.1171758319197438 * (B * 13)) + (0.8813173184360715 * (x + 1))';
console.log(
a.replace(/(\d+\.\d{3})\d+/g, '$1')
);
Split won't do a trick cause you'll have to handle all those non-numeric symbols and putting them back together.
Generic way of handling formulas is writing lexical analyzer or using some 3rd party for that.
Luckily here, you might just use replace method with regex that matches any number with period like this:
const a = '554898128.3227372 + (-1.35880 * (A * 12)) + (1.1171758319197438 * (B * 13)) + (0.8813173184360715 * (x + 1))';
const b = a.replace(/\d+\.\d+/g, function(n) {
return Math.round(Number(n));
});
console.log(b);

if x bigger than y then return x smaller than y javascript

I'am trying to make a simple calculation generator in prompt window. But it should not generate a negative number as answer, such as: x-y=-answer
My code so far:
CodepenLink
How it should look like
function myFunction() {
var randomNumber = Math.floor(Math.random() * 10);
var nxtRandomNumber = Math.floor(Math.random() * 10);
var question = prompt("What is:"+ randomNumber+ " minus " + nxtRandomNumber);
if(nxtRandomNumber > randomNumber){
return ;
}
var result = Number(randomNumber) - Number(nxtRandomNumber);
document.getElementById("demo").innerHTML = "Number:" + answer + " was right!";
}
<p>Push the button to start </p>
<button onclick="myFunction()">Calculate!</button>
<p id="demo"></p>
make sure when you calculate nxtRandomNumber to use the value of randomNumber as a minimum.
So if randomNumber is 5, nextRandomNumber should be calculated to compute a number at least equal to 'randomNumber'
for ex:
nextRandomNumber = Math.floor(Math.random() * 10) + randomNumber;
Theres a trick to generate random number between 2 values.
var nxtRandomNumber = Math.floor(Math.random() * (10 - randomNumber) + randomNumber);
From mdn
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
This example returns a random number between the specified values. The returned value is no lower than (and may possibly equal) min, and is less than (and not equal) max.>>>

Why I got NaN in this javaScript code?

First I test that every variable got a number value:
09-11 18:15:00.420:
d_drop: -1.178791867393647
drop_at_zero: 0.0731037475605623
sightHeight: 4.5
d_distance: 40
zeroRange: 10
09-11 18:15:00.420:
d_drop: true
drop_at_zero: true
sightHeight: true
d_distance: true
zeroRange: true
function isNumber (o) {
return ! isNaN (o-0) && o != null;
}
var d_drop; // in calculation this gets value 1.1789
var d_path = -d_drop - sightHeight + (drop_at_zero + sightHeight) * d_distance / zeroRange;
console.log("Path: " + d_path + " cm");
and in the log:
09-11 18:15:00.430: D/CordovaLog(1533): Path: NaN cm
WHY? I have tried to figure that out couple of hours now and no success, maybe someone has an idea, I haven't!
Thanks!
Sami
-------ANSWER IS that parse every variable when using + operand-----------
var d_path = parseFloat(-d_drop) - parseFloat(sightHeight) + (parseFloat(drop_at_zero) + parseFloat(sightHeight)) * parseFloat(d_distance) / parseFloat(zeroRange);
The addition operator + will cast things as strings if either operand is a string. You need to parse ALL of your inputs (d_drop, sightHeight, etc) as numbers before working with them.
Here's a demo of how the + overload works. Notice how the subtraction operator - is not overloaded and will always cast the operands to numbers:
var numberA = 1;
var numberB = 2;
var stringA = '3';
var stringB = '4';
numberA + numberB // 3 (number)
numberA - numberB // -1 (number)
stringA + stringB // "34" (string)
stringA - stringB // -1 (number)
numberA + stringB // "14" (string)
numberA - stringB // -3 (number)
http://jsfiddle.net/jbabey/abwhd/
At least one of your numbers is a string. sightHeight is the most likely culprit, as it would concatenate with drop_at_zero to produce a "number" with two decimal points - such a "number" is not a number, hence NaN.
Solution: use parseFloat(varname) to convert to numbers.
If you're using -d_drop as a variable name, that is probably the culprit. Variables must start with a letter.
var d_drop = -1.178791867393647,
drop_at_zero = 0.0731037475605623,
sightHeight = 4.5,
d_distance = 40,
zeroRange = 10;
var d_path = d_drop - sightHeight + (drop_at_zero + sightHeight) * d_distance / zeroRange;
console.log("Path: " + d_path + " cm"); // outputs: Path: 12.613623122848603 cm

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