toFixed Isn't Doing Anything - javascript

I'm teaching myself JavaScript and have run into a problem with toFixed(). I'm working through an amortization calculator; and, one of the steps returns a number with a huge number of decimal places. I'm trying to cut it down to 4 decimal places.
Be advised the sample code has a lot of explanatory HTML in it. It's only there so that I can work through the steps of the equation. Also, when I add one to the very long number, it adds the numeral one to end of the scientific notation.
var paymentamount;
var principal=250000;
var interestrate = 4.5;
var annualrate = interestrate/12;
var numberofpayments = 360;
document.write("This is the annuitized interest rate: "+ annualrate +"%");
document.write("<h3> Now we add 1 to the annualized interest rate</h3>");
var RplusOne = annualrate + 1;
document.write("<p> This is One Added to R: " + RplusOne + "%");
document.write("<h3>Next RplusOne is Raised to the power of N </h3>");
var RRaised = (Math.pow(RplusOne, numberofpayments)).toFixed(4);
document.write("<p>This gives us the following very long number, even thought it shouldn't: " + RRaised);
document.write("<h3>Now we add one to the very long number </h3>");
var RplusOne = RRaised + 1;
document.write("<p>Now we've added one: " + RplusOne);

From MDN's documentation:
If number is greater than 1e+21, this method simply calls Number.prototype.toString() and returns a string in exponential notation.
The problem is that you are using 4.5 as your interest rate instead of 0.045, so doing this:
Math.pow(4.5 / 12 + 1, 360)
gives you a huge number (6.151362770461608e+49 or 6.15 * 10^49 to be exact). Change your interest rate to 0.045 and you will get what you are expecting.
As for the var RplusOne = RRaised + 1 line, the problem here is that RRaised is a string because of toFixed. I would only call toFixed when you're displaying things, and not at any other time; the primary reason for this would be to avoid rounding errors in subsequent calculations, but has the added benefit that your variables remain numbers and not strings.

Related

Regarding decimal in javascript

When i am writing 11.00 it is displaying 11.00.00 otherwise its working fine on rest
if(pos == -1)
{
document.getElementById("printCheckAmount").textContent = "$" + checkObj.checkAmount + ".00";
}
else
{
var integer = enterCheckAmount.substring(0,pos);
var decimals = enterCheckAmount.substring(pos+1);
while(decimals.length<2) decimals=decimals+'0';
enterCheckAmount = integer + '.' + decimals;
document.getElementById("printCheckAmount").textContent = "$" + checkObj.checkAmount;
}
JavaScript doesn't have a variable type for decimal numbers. It has only Number. If you want to display an integer as a decimal number with two zeros after the decimal point you can use the method toFixed.
Here is an example:
var myNumber = 11;
var myDecimalNumber = myNumber.toFixed(2);
console.log(myDecimalNumber) // will output 11.00
Thus there is no need to concatenate strings and add ".00" manually to your number.
Beyond this you can use the methods parseInt and parseFloat. Let's say you have a variable of type string with the value "11 pieces". You can get the integer with this line of code:
var myString = "11 pieces";
var myInteger = parseInt(myString, 10);
console.log(myInteger); // will output 11
If you have something similar like this, you are better off with this methods instead of cuting substrings.
I wish you a lot of success in refactoring your code and a warm welcome to the StackOverflow community.

Javascript, rounding and calculating values against original values

I'm trying to calculate a series of values which should aggregate to the same as the Original Value.
If you look at the above example, you can see that the aggregated cost and billed figures are aggregating to 239.99 and 219.98 respectively. They obviously need to aggregate to 240 and 220 respectively.
The cost and billed figures are calculated when Hours changes (by using a jQuery on change function). The multiplier is determined by dividing the Original Value Hours by the number specified in the Calculated Values Hours below.
(0.2 / 0.7) = 0.28571428571428575
(0.3 / 0.7) = 0.4285714285714286
Self-evidently, the figures need to aggregate to the Original Values.
This is an issue no doubt to do with floating point precision and rounding and I've tried using the following function without success:-
function to2DP(num, fixed) {
var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?');
return num.toString().match(re)[0];
}
$("#splitTimeContainer").on("change", ".changeHours", function(e) {
var splitID = $("#splitID").val();
var splitOrigCost = $("#splitOrigCost").val();
var splitOrigBilled = $("#splitOrigBilled").val();
var splitOrigHours = $("#splitOrigHours").val();
var i = 1;
var divideMe = $(this).val();
var coEfficient = (divideMe/splitOrigHours);
var newCost = to2DP((coEfficient * splitOrigCost), 2);
var newBilled = to2DP((coEfficient * splitOrigBilled), 2);
var parent = $(this).parent().parent();
parent.find('.changeCost').val(newCost);
parent.find('.changeBilled').val(newBilled);
});
As well as using toFixed, but again without success.
Anyone have any suggestions at how I go about achieving this?
This question is more about rounding and mathematics.
I recommend to use different rounding to even. This rounding at least has no bias so it will not systematically increase or decrease values.
Another problem is that even with this rounding there is no guarantee that sum of values will match due to odd number of calculated values.
In this particular example this rounding will achieve cost 240 and billed 220.01.
This problem in my opinion has not optimal solution.
Consider this:
Hours: 0.9, Cost 100
hours: 0.3, cost 33.33
hours: 0.3, cost 33.33
hours: 0.3, cost 33.33
There is no way how to make this working.
You might want to consider adding the amount lost during division to one or more values.
Splitwise also does that to ensure no loss of value.

Why is my tip calculator multiplying my Total by 10?

I was just trying to make a simple tip calculator that I thought was going to take 5 seconds but something I'm not getting..
Why does this
subTotal = prompt('Total before Tip');
tipPercent = prompt('Percentage to Tip (Please use decimal)');
tip=tipPercent*subTotal;
total = subTotal+tip;
alert('Tip is ' + tip + ' Total is ' + total );
compute total to 10 times what it should be? I checked every other variable and it computes correctly except for subTotal + tip.
total = subTotal+tip;
This concatenates the subTotal string with the tip string.
Cast your values to float first before adding them together.
subTotal = parseFloat(prompt('Total before Tip'));
tipPercent = parseFloat(prompt('Percentage to Tip (Please use decimal)'));
JavaScript is treating subtotal and total as string not floats or integers
conversion will solve your issue like this
Here i am using the Number function to convert any string to the appropriate number type
subTotal = prompt('Total before Tip');
tipPercent = prompt('Percentage to Tip (Please use decimal)');
tip=tipPercent*subTotal;
total = Number(subTotal)+Number(tip);
alert('Tip is ' + tip + ' Total is ' + total );
your prompts are taking in strings and its simply concatenating the strings.
You need to convert the strings to numbers, in the case of your tip calculation js is converting the strings as numbers, but the addition for total its not. try something like this (add the parseInt() before the values to force JS to deal with them as integers):
total = parseInt(subTotal)+parseInt(tip);
Several answers above are correct. The input is STRING but you want to convert them to numbers to do the math on them.
Simplest solution is to convert them as you get the input from the user:
subTotal = Number(prompt('Total before Tip'));
tipPercent = Number(prompt('Percentage to Tip (Please use decimal)'));
Enter 20.00 then .15 will result in 23
The value coming from prompt is not integer. Read up: Window.prompt() - Web APIs | MDN
Convert it using parseInt() - JavaScript | MDN.
Also, you are missing the division by 100 while calculating the tip.
One more thing - if you are not declaring the variables using var, they will be global variables!
Check out this working code snippet:
var subTotal = parseInt(prompt('Total before Tip'));
var tipPercent = parseInt(prompt('Percentage to Tip (Please use decimal)'));
var tip = tipPercent * subTotal/100;
var total = subTotal + tip;
alert('Tip is ' + tip + ' Total is ' + total);

JQuery not showing correct decimal output

My problem with this is, everything is fine up to two decimal places when its preceded 1-9, however if the number is a 10th, then my script will only show to one decimal place.
E.g 200.19, 5000.42, 12.98 << will be fine however if the output should be 123.10 it will display 123.1
Here's my code:
jQuery(document).ready(function() {
function ReplaceNumberWithCommas(yourNumber) {
//Seperates the components of the number
var n= yourNumber.toString().split(".");
//Comma-fies the first part
n[0] = n[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
//Combines the two sections
return n.join(".");
}
function loanCalc() {
//Get the parameter from the form
var rate=jQuery('#start_rate').val();
var priceValue=jQuery('#input_1_2').val();
console.log("price value before"+priceValue);
if(priceValue.indexOf('£') == 0) {
var strEnd=jQuery('#input_1_2').val().indexOf(',') - 1;
priceValue=parseInt(priceValue.substr(1,priceValue.strEnd))*1000;
}else{
priceValue=priceValue;
}
var princ = parseInt(priceValue);
var term = parseInt(jQuery('#input_1_3').val());
var intr = rate / 1200;
console.log("price"+priceValue+" term"+term+" rate"+rate);
var calculation = princ * intr / (1 - (Math.pow(1/(1 + intr), term)));
console.log("paymenet"+calculation);
var rePayment= calculation*term;
var costOfCredit=princ-rePayment;
//set the value
jQuery('#figure').html('£'+ ReplaceNumberWithCommas(calculation.toFixed(2)));
jQuery('#rate').html(rate+"%");
jQuery('#total').html('£' +
ReplaceNumberWithCommas(rePayment.toFixed(2)));
jQuery('#credit').html('£' + ReplaceNumberWithCommas(
Math.abs(costOfCredit.toFixed(2 ))));
As you can probably guess, there are 3 fields that I am displaying, the calculation, which is a percentage, 'rePayment' and 'costOfCredit'. The weird thing is 'rePayment' works fine and has no problem showing the 2nd decimal place even if its a 10th/ends with zero.
So my question is can you guys help me find what my problem is with getting the 2nd decimal place to show is?
When you call Math.abs(), it's converting the string with 2 digits after the decimal back to a number, which loses the trailing zeroes. You should call Math.abs() first, then call toFixed() on this to add the trailing zeroes.
jQuery('#credit').html('£' +
ReplaceNumberWithCommas(Math.abs(costOfCredit).toFixed(2)));

toFixed method doesn't work on user input but works on other vars in javascript, snippet included

I wanted feedback on why toFixed would not work in my JS alert when attached to the user input var usergb. Was a curious thing. I've been encouraged to post and I did not see any other questions out here regarding toFixed issues with user-input vars.
var downloadspeed = function () {
var usergb = prompt("How many gigabytes do you wish to download at 56 kilobits per second?");
console.log(usergb);
var hours = (usergb*8388608)/201600;
console.log(hours);
var days = (usergb*8388608)/4838400;
console.log(days);
//below in the alert is where you will see it, after the first concatenated string, I'd like to type usergb.toFixed(2) but it won't take.
alert("The number of hours it will take to download a " + usergb + " GB file at 56 kilobits per second is " + hours.toFixed(2) + " hours. This might be a big number. So, in terms of days to download, it'll take " + days.toFixed(2) + " days to download. This is why we have faster broadband speeds nowadays and why we have video streaming.");
}
downloadspeed();
The error I get is that it is not a function.
Grazie, Lou
toFixed is a method on a Number ...
prompt returns a String
try parseFloat(usergb).toFixed(2)
You have to use toFixed() on the number:
parseFloat(usergb).toFixed(2)
The prompt function returns a string, you can not use toFixed() on strings, only on numbers.
You need to cast the input as a number:
var usergb = +prompt("How many gigabytes do you wish to download at 56 kilobits per second?");
You can parse the input in the Number type. Example plunkr
var downloadspeed = function() {
var input = prompt("How many gigabytes do you wish to download at 56 kilobits per second?");
var usergb = new Number(input);
if(isNaN(usergb))
{
alert("You must input a number");
return;
}
console.log(usergb);
var hours = (usergb * 8388608) / 201600;
console.log(hours);
var days = (usergb * 8388608) / 4838400;
console.log(days);
//below in the alert is where you will see it, after the first concatenated string, I'd like to type usergb.toFixed(2) but it won't take.
alert("The number of hours it will take to download a " + usergb + " GB file at 56 kilobits per second is " + hours.toFixed(2) + " hours. This might be a big number. So, in terms of days to download, it'll take " + days.toFixed(2) + " days to download. This is why we have faster broadband speeds nowadays and why we have video streaming.");
}
downloadspeed();

Categories

Resources