I'm attempting to build an app that calculates sales metrics. I have run into an unusual problem in my build.
Part of the app allows users to increase/decrease a variable by 5% and then see how that will effect an overall metric. It also allows the user to see the percentage increase/decrease.
I have the functionality working roughly as intended, however if I enter a number lower than 20 into the input and then try in increase it with my incrementing function it only increments once and then stops.
If the number I enter into the input is 20 or greater it increments in the intended way.
Below is my angular code:
function controller ($scope) {
$scope.firstNumber = 0;
$scope.firstPercent = 0;
$scope.increase = function(id) {
var A = parseInt(id);
var B = A * 5/100;
var C = 0;
var C = A + B;
if (id === $scope.firstNumber) {
$scope.firstNumber = C;
$scope.firstPercent = $scope.firstPercent + 5;
}
};
$scope.decrease = function(id) {
var A = parseInt(id);
var B = A * 5/100;
var C = 0;
var C = A - B;
if (id === $scope.firstNumber) {
$scope.firstNumber = C;
$scope.firstPercent = $scope.firstPercent - 5;
}
};
I can't see anything wrong with my maths, my thinking is that perhaps I'm approaching angular in the wrong way. However I'm not sure.
I have put together a fiddle that shows the full code.
jsFiddle
I have updated the fiddle to use parseFloat. Seems like the numbers are incrementing now.
var A = parseFloat(id);
http://jsfiddle.net/kjDx7/1/
The reason why it was working with values above 20 was that it was just reading the part before decimals each time it tried to increase. So 20 became 21 and 22.05 and so on. As long the the value before decimal kept changing, it showed different (but incorrect) answers.
On the other hand, 10 became 10.5 which when parsed yielded 10. As you can see, this cycle continued endlessly.
The reason why you face the issue is because 5% of anything less than or equal to 20 is less than or equal to 1.
When you parseInt() the value, you always end up with the same number again.
Take 15 for example.
5% of 15 = 15.75
After parseInt(), you get the value 15 again.
You use the same value to increment / decrement each time.
Hence for values below 20, you don't get any changes.
As #Akash suggests, use parseFloat() instead - or why even do that when the value that you get is float anyway
I made a fork of your fiddle. I'm not completely sure what you want to achive.
Take a look at this fiddle.
$scope.increase = function() {
$scope.firstPercent = $scope.firstPercent + 5;
var A = $scope.firstNumber;
var B = (A / 100) * $scope.firstPercent;
var C = A + B;
$scope.firstNumberWithPercent = C;
};
update
After posting, i see that question is already answered. But is this what you really want? When you hit increase, it takes 5 % off of the number in the input field. That is ok, but when you hit decrease after that, it takes 5 % off the number in the same field. So your starting point is different.
100 + 5/100 = 105
105 - 5/105 = 99,75
Related
I've been having a problem that when my auto clicker in my clicker game goes fast enough to get to 200 thousand, it starts to lag, and then it doesn't function properly, or as fast.
Is there a way to make 100 thousand turn into 100K, and 101 thousand turn into 101K without being repetitive?
I tried this with my original code, and realized putting up to 1000 suffixes into each function would be a little too hard:
if (number >= 100000) {
document.getElementById(ID).innerHTML = "100K"
}
if (number >= 101000) {
document.getElementById(ID).innerHTML = "101K"
}
and on and on.
I don't want multiple if statements!
This would work, but it would take up way too much space, and I know there is an easier way to it, but I just couldn't find it. Can anyone provide a way to do this?
Try separating the job of formatting your number into a different function.
SUFFIXES = 'KMBTqQsSOND' // or whatever you'd like them to be
function getSuffixedNumber(num) {
var power = Math.floor(Math.log10(num));
var index = Math.floor(power / 3);
num = Math.round(num / Math.pow(10, (index * 3))); // first 3 digits of the number
return num + (SUFFIXES[index - 1] || ''); // default to no suffix if we get an out of bounds index
}
You can call the function like this: var x = getSuffixedNumber(101000), the value of x will be "101K".
First off, I have to say that I am very new to Javascript and programming in general so it's possible that the issue is related to my (current) lack of knowledge.
I've tried to make a simple game where a computer thinks of a random number between 0 and 10 and the user tries to guess that number by typing his guess in the text field. If the number is correct, the user gets the message that they guessed the number correctly and otherwise, they get the message that the numbers are not correct.
The first part works as intended. The problem is the score counter.
So this is the part of the HTML code that I wrote for the counter:
<p id="points">Number of points: </p><span id="points-number">0</span>
And this is the code that I wrote in JS:
<script type="text/javascript">
document.getElementById("instructions").onclick = function() {
alert("You need to guess the number that your computer imagined. Viable numbers are between 0 and 10. Every time you guess the number, score increases by 1 and every time you miss, you will lose a point")
}
document.getElementById("guess-number").onclick = function() {
var ourNumber;
var randomNumber;
var pointsNumber = 0;
randomNumber = Math.floor(Math.random() * 10);
ourNumber = document.getElementById("input").value;
if (ourNumber == randomNumber) {
alert("The numbers are equal!");
pointsNumber+=1;
var result = document.getElementById("points-number");
result.innerHTML = pointsNumber;
} else {
alert("The numbers are not equal! The number that your computer imagined is:" + randomNumber + ", and our number is: " + ourNumber);
pointsNumber-=1;
var result = document.getElementById("points-number");
result.innerHTML = pointsNumber;
}
}
</script>
Now here's the problem...whenever the user misses the number, the number of points goes to -1. But if he misses the second time, it stays at -1, it doesn't decrease further. After the user guesses the number, the value changes from -1 to 1. But, if he guesses again, it doesn't increase to 2, it stays at 1. Then when he misses, it jumps back to -1 and vice versa.
So, I believe I am missing something here, what should I do to make the counter work as intended? In other words, to make the score increase by 1 every time the user guesses the random number and make it decrease by 1 every time he doesn't get it right?
Thanks in advance.
basically, you are always starting with
var pointsNumber = 0;
instead, you should use:
var pointsNumber = + document.getElementById("points-number").innerHTML;
bonus:
and yes instead of:
randomNumber = Math.floor(Math.random() * 10);
use:
randomNumber = Math.floor(Math.random() * 11);
because, Math.random() lies between 0 (inclusive) and 1 (EXCLUSIVE), so could never reach 10.
see more about Math.random() at: https://www.w3schools.com/js/js_random.asp
You need to declare pointsNumber outside of the function:
var pointsNumber = 0;
document.getElementById("guess-number").onclick = function() {
var ourNumber;
var randomNumber;
Otherwise, each time the onclick function is called, you declare pointsNumber and set it to 0. Then it gets +1 or -1 depending on the if/else, which explains the behavior you are observing.
I have table like this:
The total of the Percentage column must be 100%, but I'm getting 100.01%.
Here's my code:
var hourSlow = $("#input-me-slow").val();
var slowTime = moment.duration(hourSlow).asHours();
// slow time return 2.1666666666666665
var hourIdle = $("#input-me-idle").val();
var idleTime = moment.duration(hourIdle).asHours()
// idle time return 1
var hourEco = $("#input-me-eco").val();
var ecoTime = moment.duration(hourEco).asHours();
// ecoTime return 20.166666666666668
var hourSpeed = $("#input-me-speed").val();
var speedTime = moment.duration(hourSpeed).asHours();
// speedTime return 0.6666666666666666
var fTime = "24:00"
var dfTime = moment.duration(fTime).asHours();
// dfTime return 24
var totalTime = dfTime-speedTime-ecoTime-slowTime-idleTime;
// totalTime return -2.220446049250313e-15
// Here for display it to table, the problem is here
var fPercent = toHour(fullTime); //return 2.78
var ePercent = toHour(ecoTime); //return 84.03
var sPercent = toHour(slowTime); //return 9.03
var iPercent = toHour(idleTime); //return 4.17
$("#me_fullpercen").text(addCommas(fPercent));
$("#me_ecopercen").text(addCommas(ePercent));
$("#me_slowpercen").text(addCommas(sPercent));
$("#me_idlepercen").text(addCommas(iPercent));
// here the function of toHour (I dont know maybe the problem is here)
function toHour(num) {
var result = (num / 24) * 100;
return result ;
}
I would rather not round the percentage to 100%, as that would be less precise.
How can I make my percentage 100% instead of 100.01%?
This is a common problem, and no matter how precise you try to be, the computer will need to round numbers with repeating decimals at some point. Here's some posts that deal with it:
How to make rounded percentages add up to 100%
How to deal with the sum of rounded percentage not being 100?
In those posts you can read about many complex ways to get very close to 100%, but basically there is no right way to do this - when it's all boiled down it's still going to be an estimate - not exactly precise because we're dealing with not-precise numbers. That's just the nature of the beast.
Your program is going to round numbers the wrong way because it's a computer, and it's not intelligent.
Depending on your application, you may want to invest time into reading how to do those complex methods, and maybe you'll get really close.
Add a Footnote
Any path you choose, you'll probably end up putting a footnote explaining this problem anyway. Something like this:
*Because of rounding, these values may not add up to 100%.
this is continuation of last successful topic
jquery: percentage of two numbers
First of all I want to thank you for your prompt support of previuous post.
Now I would like to make my script a little bit more complicated. I want to achive the following: If I insert PRICE1 and PRICE2 to have RATE between THEM, then I can change the RATE with other value and PRICE2 to change to the corespondent value according to RATE value.
My script of calculation is close to be correct, but my low knowledge about JQuery make me to ask you where I do something wrong.
Thank you for your support!
<script src="libs/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$("#PRICE1, #PRICE2").change(function() {
var result = parseFloat(parseFloat($("#PRICE1").val(), 10) - parseFloat($("#PRICE1").val(), 10))/ parseFloat($("#PRICE2").val(), 10) * 100;
$('#RATE').val(result||'');
})
else {
$("#PRICE1, #RATE").change(function() {
var result = parseFloat(parseFloat($("#PRICE1").val(), 10) * parseFloat($("#RATE").val(), 10))/ 100 + parseFloat($("#PRICE1").val(), 10);
$('#PRICE2').val(result||'');
})}
});
</script>
EDITED:
THE CODE ALMOST WORKING CORRECTLY WHICH MIGHT HELP OTHERS:
$(document).ready(function(){
$("#priceOne, #priceTwo").change(function() {
var priceOne = parseFloat($("#priceOne").val());
var priceTwo = parseFloat($("#priceTwo").val());
$('#Rate').val((priceTwo - priceOne) / priceOne * 100); // Set the rate
});
// If price one or the rate is changed, adjust price two.
$("#priceOne, #RATE").change(function() {
var priceOne = parseFloat($("#priceOne").val());
var rate = parseFloat($("#Rate").val());
$('#priceTwo').val((priceOne * rate)/ 100 + priceOne);
});
})
Thank you everyone who help me!!!
There is a else and no matching if. I'm not sure what you're trying to achieve, but some condition needs to be checked.
I'm going to try and code what it appears you need. But I'm going to rename your variables, not only because allcaps are hard to type, but unless it's a constant or a macro, they shouldn't be used.
// In ready() callback
// #NOTE - This does NO error checking for division by 0 or other NaN operations.
// If price two is changed, adjust the rate.
$("#priceTwo").change(function() {
var priceOne = parseFloat($("#priceOne").val());
var priceTwo = parseFloat($(this).val());
$("#rate").val(priceTwo / priceOne); // Set the rate
});
// If price one or the rate is changed, adjust price two.
$("#rate #priceOne").change(function() {
var priceOne = parseFloat($("#priceOne").val());
var rate = parseFloat($("#rate").val());
$("#priceTwo").val(priceOne * rate);
});
There are a few things about your code that needs attention:
parseFloat doesn't take a radix argument, the 10 you pass it is ignored.
parseFloat(parseFloat(... is pointless, I'm not sure why you've done this.
Don't use jQuery to select the same element multiple times in the same scope. Save the value and re-use it - save yourself some cycles.
As I mentioned, don't name your variables in all capitals unless they are some sort of constant that should never be changed, it's good to have clean style habits.
Hey again everyone. Yet again i am having some problems with trying to get the match correct on this Excel Spreadsheet to JavaScript conversion.
Here is the excel formula:
=IF(IF($B$7=TRUE,$B$28/$B$10,$B$28/$B$5)>1,1,IF($B$7=TRUE,$B$28/$B$10,$B$28/$B$5))
WHERE
B7 = TRUE
B28 = 76800
B10 = 892015
B5 = 999500
And this is my JavaScript i have so far:
function percent(x) { return Math.round((x-0)*100) + '%'; }
if($('#section179').is(':checked'))
{
var percentRepaid = $("#rev3DScanYear").val() / $("#section179Real").val();
if (percentRepaid > 1)
{
$("#paymentCashPer").val('100.00');
}else
{
percentRepaid = $("#rev3DScanYear").val() / $("#SalePrice").val();
$("#paymentCashPer").val(percent(percentRepaid));
}
}else
{
//to be done
}
WHERE
rev3DScanYear = 76800
SalePrice = 999500
section179Real = 892015
For the JavaScript code i keep getting a value of 8% and i should be getting a value of 8.61% as it has on the spreadsheet.
As always, any help would be great! :o)
David
Math.round((x-0)*100) makes x an integer.
You could try Math.round(((x-0)*100)*100)/100 which makes the x = 8.609720... into x=861 and then divides it to get the x=8.61 you're looking for, which is what they would suggest here.
...Also, not really sure why you're subtracting 0 from x...?
Ok, so I've been looking at this again, and I think I didn't look deeply enough the first time.
The logic, if I understand it, is this:
If Section179 is checked then Divisor is Section179Real, else it is SalePrice.
Give me the smaller of 1.00 or (rev3DScanYear / Divisor).
If that's correct, you can do it in excel with =MIN(1,$B28/IF($B$7=TRUE,$B$10,$B$5)) (same references), which means that the following should do what you want it to:
var Divisor = $("#SalePrice");
if($('#section179').is(':checked'))
{
Divisor = $("#section179Real");
}
$("#paymentCashPer").val(Math.round(100*(Math.min(1, $("#rev3DScanYear")/Divisor)*100)/100;