I have a simple form, with 5 textboxes and 3 answers (also textboxes). The form calculates a result for the user with number inputs. My problem is my calculation does not work in IE, but works fine in both Chrome and Firefox.
What's wrong?
Here is my function:
function addNumbers()
{
var val1 = Number(document.getElementById("value1").value);
var val2 = Number(document.getElementById("value2").value);
var val3 = Number(document.getElementById("value3").value);
var val4 = Number(document.getElementById("value4").value);
var val5 = Number(document.getElementById("value5").value);
var val6 = '100';
var ansD1 = document.getElementById("answer1");
ansD1.value = Number((val1 * val2) * (val4 / val6));
var ansD2 = document.getElementById("answer2");
ansD2.value = Number((val1 * val3) * (val5 / val6));
var ansD3 = document.getElementById("answer3");
ansD3.value = Number (ansD1.value - ansD2.value);
}
Change this line:
var val6 = '100';
to this:
var val6 = 100;
You want all your values to be actual numbers (not strings) so you can do math on them.
Also, you don't need the Number() in these lines because the result of the numeric math is already a number. Plus the assignment to the answer fields is just going to convert the result to a string anyway:
ansD1.value = Number((val1 * val2)*(val4/val6));
They can just be this:
ansD1.value = (val1 * val2)*(val4/val6);
The modified code works fine in IE here: http://jsfiddle.net/jfriend00/5WFRA/.
Instead of Number use parseInt, otherwise they are treated as strings
Related
Javascript output showing Nan when i enter large values like 6564646464,6516654,555 input values?
$("#calculate").click(function () {
var need_hotel = $("#hotel_need").val();
var event_day = $("#event_day").val();
var result_1 = parseFloat(need_hotel * event_day);
var result_2 = result_1 * 165;
var result_3 = result_2 * 0.03;
$("#ans1").text(result_1.toFixed(2));
$("#ans2").text(result_2.toFixed(2));
$("#ans3").text('£' + (result_3).toLocaleString('en'));
$("#results_container").show();
});
Javascript has iffy support for such large numbers
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER
You might wanna try BigInt
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
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;
}
This is the rounding function we are using (which is taken from stackoverflow answers on how to round). It rounds half up to 2dp (by default)
e.g. 2.185 should go to 2.19
function myRound(num, places) {
if (places== undefined) {
// default to 2dp
return Math.round(num* 100) / 100;
}
var mult = Math.pow(10,places);
return Math.round(num* mult) / mult;
}
It has worked well but now we have found some errors in it (in both chrome and running as jscript classic asp on IIS 7.5).
E.g.:
alert(myRound(2.185)); // = 2.19
alert (myRound(122.185)); // = 122.19
alert (myRound(511.185)); // = 511.19
alert (myRound(522.185)); // = 522.18 FAIL!!!!
alert (myRound(625.185)); // = 625.18 FAIL!!!!
Does anyone know:
Why this happens.
How we can round half up to 2 dp without random rounding errors like this.
update: OK, the crux of the problem is that in js, 625.185 * 100 = 62518.499999
How can we get over this?
Your problem is not easily resolved. It occurs because IEEE doubles use a binary representation that cannot exactly represent all decimals. The closest internal representation to 625.185 is 625.18499999999994543031789362430572509765625, which is ever so slightly less than 625.185, and for which the correct rounding is downwards.
Depending on your circumstances, you might get away with the following:
Math.round(Math.round(625.185 * 1000) / 10) / 100 // evaluates to 625.19
This isn't strictly correct, however, since, e.g., it will round, 625.1847 upwards to 625.19. Only use it if you know that the input will never have more than three decimal places.
A simpler option is to add a small epsilon before rounding:
Math.round(625.185 * 100 + 1e-6) / 100
This is still a compromise, since you might conceivably have a number that is very slightly less than 625.185, but it's probably more robust than the first solution. Watch out for negative numbers, though.
Try using toFixed function on value.
example is below:
var value = parseFloat(2.185);
var fixed = value.toFixed(2);
alert(fixed);
I tried and it worked well.
EDIT: You can always transform string to number using parseFloat(stringVar).
EDIT2:
function myRound(num, places) {
return parseFloat(num.toFixed(places));
}
EDIT 3:
Updated answer, tested and working:
function myRound(num, places) {
if (places== undefined) {
places = 2;
}
var mult = Math.pow(10,places + 1);
var mult2 = Math.pow(10,places);
return Math.round(num* mult / 10) / mult2;
}
EDIT 4:
Tested on most examples noted in comments:
function myRound(num, places) {
if (places== undefined) {
places = 2;
}
var mult = Math.pow(10,places);
var val = num* mult;
var intVal = parseInt(val);
var floatVal = parseFloat(val);
if (intVal < floatVal) {
val += 0.1;
}
return Math.round(val) / mult;
}
EDIT 5:
Only solution that I managed to find is to use strings to get round on exact decimal.
Solution is pasted below, with String prototype extension method, replaceAt.
Please check and let me know if anyone finds some example that is not working.
function myRound2(num, places) {
var retVal = null;
if (places == undefined) {
places = 2;
}
var splits = num.split('.');
if (splits && splits.length <= 2) {
var wholePart = splits[0];
var decimalPart = null;
if (splits.length > 1) {
decimalPart = splits[1];
}
if (decimalPart && decimalPart.length > places) {
var roundingDigit = parseInt(decimalPart[places]);
var previousDigit = parseInt(decimalPart[places - 1]);
var increment = (roundingDigit < 5) ? 0 : 1;
previousDigit = previousDigit + increment;
decimalPart = decimalPart.replaceAt(places - 1, previousDigit + '').substr(0, places);
}
retVal = parseFloat(wholePart + '.' + decimalPart);
}
return retVal;
}
String.prototype.replaceAt = function (index, character) {
return this.substr(0, index) + character + this.substr(index + character.length);
}
OK, found a "complete" solution to the issue.
Firstly, donwnloaded Big.js from here: https://github.com/MikeMcl/big.js/
Then modified the source so it would work with jscript/asp:
/* big.js v2.1.0 https://github.com/MikeMcl/big.js/LICENCE */
var Big = (function ( global ) {
'use strict';
:
// EXPORT
return Big;
})( this );
Then did my calculation using Big types and used the Big toFixed(dp), then converted back into a number thusly:
var bigMult = new Big (multiplier);
var bigLineStake = new Big(lineStake);
var bigWin = bigLineStake.times(bigMult);
var strWin = bigWin.toFixed(2); // this does the rounding correctly.
var win = parseFloat(strWin); // back to a number!
This basically uses Bigs own rounding in its toFixed, which seems to work correctly in all cases.
Shame Big doesnt have a method to convert back to a number without having to go through a string.
I am building a basic application to learn more, but have came across an issue.
I have 3 input boxes. people, bill, tip. the maths is as follows:
(bill + tip) / people. When i try to divide in my code it seems to add onto the end of my total.
So far i have this. http://jsfiddle.net/ma9ic/a8eJT/
var updateTotal = function () {
var people = parseInt($('#people').val());
var bill = ($('#bill').val());
var tip = ($('#tip').val());
var billTip = bill + tip;
var billTipPeople = billTip / people;
$('#total').text("£" + billTipPeople)
If i could get pointed in the right direction that would be great :)
You're pretty close. I got it working like this
var updateTotal = function () {
var people = parseInt($('#people').val(),10);
var bill = parseFloat($('#bill').val());
var tip = parseFloat($('#tip').val());
var billTip = bill + tip;
var billTipPeople = billTip / people;
if (isNaN(billTipPeople)) billTipPeople = 0; // output zero if NaN
$('#total').text("£" + billTipPeople.toFixed(2))
The issue is that javascript has some weird rules about string concatenation. "1"+"1" == "11". You need to be explicit every time.
parseInt GOTCHA: ALWAYS use the second (optional) base parameter of parseInt. Values like "015" will be parsed as octal into the decimal number 13 otherwise. Hence the popular joke, "Why do programmers confuse Halloween and Christmas? Because OCT31 == DEC25!"
bill + tip will perform string concatenation, not addition, because they are both string. At least one of the operands has to be a number if you want to perform addition.
While parseFloat and parseInt work, using the unary plus operator is shorter to write and you don't have to worry about the type of number:
var people = +$('#people').val();
var bill = +$('#bill').val();
var tip = +$('#tip').val();
This works as long as the input value only consists of a number. But if the input only starts with a number, e.g. "5 foo" and you want to extract the number from the beginning of the string, you really have to use parseInt or parseFloat.
Your bill and tip variables are strings. Try using parseFloat(). Using the addition sign (+) on two strings will simply concatenate them.
var bill = parseFloat($('#bill').val());
var tip = parseFloat($('#tip').val());
While you used parseInt() in one case, why didn't you follow same path in similar situations?
Anyway, here's how I have modified your code:
$(document).ready(function () {
$('input#bill, input#tip').blur(function () {
var num = parseFloat($(this).val());
if (isNaN(num)) {
return;
}
var cleanNum = num.toFixed(2);
$(this).val(cleanNum);
if (num / cleanNum < 1) {}
});
$('#people, #bill, #tip').keyup(function () {
updateTotal();
});
var updateTotal = function () {
var people = parseInt($('#people').val());
if (isNaN(people) || people === 0) {
return;
}
var bill = parseFloat($('#bill').val());
if (isNaN(bill)) {
bill = 0;
}
var tip = parseFloat($('#tip').val());
if (isNaN(tip)) {
tip = 0;
}
var billTip = bill + tip;
var billTipPeople = billTip / people;
$('#total').text("£" + billTipPeople);
// round up to 2 d.p. like below:
// $('#total').text("£" + billTipPeople.toFixed(2));
};
});
To save you from coming back again and asking why your app has decided to come up another crazy behaviour, I've added the following checks:
When user enters number of people, even though we are not ready to enter total cost of bill, it is updated as NaN. We prevent this nasty behaviour by...
if (isNaN(num)) {
return;
}
We take same precaution in the updateTotal() function. Moreover, watch out for division by 0!* I give tips onle when I'm with my gf, otherwise, a person like me will break your app...
if (isNaN(people) || people === 0) {
return;
}
Here's the fiddle >> http://jsfiddle.net/a8eJT/11/
Try to use parseInt() and parseFloat() in javascript.When you did with out using these then it will treat as strings.
try
var updateTotal = function () {
var people = parseInt($('#people').val());
var bill = parseInt($('#bill').val());
var tip = parseInt($('#tip').val());
var billTip = bill + tip;
var billTipPeople = billTip / people;
$('#total').text("£" + billTipPeople)
I have added parseint to both bill & tip
I have this JavaScript function (see below). It only return whole number, it only works when I inputted a whole number. But when I inputted decimal value it doesn't work.
What should I do to handle decimal value?
function calc()
{
var license=parseInt(document.getElementById("license").value);
var service=parseInt(document.getElementById("service").value);
var amount=parseInt(license)+parseInt(service);
var mult=service*(parseInt(document.getElementById("preterms").value) / 100);
var mult1=service*(parseInt(document.getElementById("blueterms").value) / 100);
var mult2=service*(parseInt(document.getElementById("configterms").value) / 100);
document.getElementById("amount").value = amount;
document.getElementById("pre").value = mult;
document.getElementById("blue").value = mult1;
document.getElementById("config").value = mult2;
}
Thanks in advance.
change parseInt to parseFloat, like
var license=parseInt(document.getElementById("license").value);
to
var license=parseFloat(document.getElementById("license").value);
Since you are working with decimal values You need to use parseFloat instead of parseInt
ex:
function calc() {
var license = parseFloat(document.getElementById("license").value);
var service = parseFloat(document.getElementById("service").value);
var amount = parseFloat(license) + parseFloat(service);
var mult = service * (parseFloat(document.getElementById("preterms").value) / 100);
var mult1 = service * (parseFloat(document.getElementById("blueterms").value) / 100);
var mult2 = service * (parseFloat(document.getElementById("configterms").value) / 100);
document.getElementById("amount").value = amount;
document.getElementById("pre").value = mult;
document.getElementById("blue").value = mult1;
document.getElementById("config").value = mult2;
}
It looks like folks suggested using parseFloat. The next issue you're likely to run into is formatting the output. You can use toFixed to output your percentages with a fixed number of decimals:
(12.34567).toFixed(2)
// => "12.35"