I am having a issue trying to work out the remaining percentage between 2 numbers.
I have worked out how to get the current percentage by using the following function:
function GetPercentage(x,y){
return ((x /y) * 100).toFixed(0);
}
The part I need help with is to get the remaining percentage.
For Example:
Lets say the maximum is 31 and I have a value of 1, how can I return the value 97%
Using my function above if I use GetPercentage(1,31) it would return 3.
However, I need help with the function to return 97.
I have tried using the following but doesn't seem to work.. I am guessing my Math isn't correct and hoping someone can correct me.
alert(GetPercentage(1,31) + "%" + " used. " + availablePercentage(5,31) + "% still available"); // trying to make it say: 3% used. 97% still available
function GetPercentage(x,y){
return ((x / y) * 100).toFixed(0);
}
function availablePercentage(x,y){
return ((y-x)/100).toFixed(0);
}
It sounds like you need to subtract the number you're computing from 100.
function availablePercentage(x,y){
return 100 - GetPercentage(x, y);
}
I believe a suitable formula for what you are looking for is
((y - x) / y) * 100
so for the inputs x = 1 and y = 31 you would get
((31 - 1) / 31) * 100
(30 / 31) * 100
96.77
I'm going to guess that you mean, given there are 31 things to do and I have done 1 what is the % that remain to do?
You need to subtract from 1 ( and multiply by 100 if you want percent from 0-100)
eg
function todoPercent(numTodo, numDone){
return (1-numDONE/numTodo)*100;
}
Related
I have the following which returns the rotation in degrees of an object, lensParentRight, through 360.
This is in Adobe Animate HTML5 Canvas (create.js/easel.js would apply). cylinderAngle is just an offset.
var cylinderAngleText = Math.abs((Math.round(((root.lensParentRight.rotation + cylinderAngle) * 100) / 100))) + "\u00B0";
I want to keep the angle returned between 1 and 180.
How would this be done in JavaScript?
You could always limit your variable values using mod "%" at end of your mathematical expression.
((exp)%180) in your case.
I hope that helps.
To add 2 numbers and constrain the value to lie within a specified range requires that you implement overflow on the results of the addition. Something like this:
function add_and_constrain_to_range( a, b, lo, hi ) {
const range = hi - lo ;
const sum = a + b ;
const result = lo + ( sum % range ) ;
return result;
}
With d3.js we can achieve eased time out of normalized time t, typically in the range [0,1]
For example:
d3.easeCubic(0.25) = 0.0625
How can we reverse that, how can we find x given known y ?
d3.easeCubic(X) = 0.0625,
X ???
The answer here is cubic root, but still.
The problem is in reusability, ease function can change to d3.easeExpIn, or `d3.easeCircleOut, or any other, do you need to invent reverse functions on your own, or are they hidden anywhere ?
Firstly, your math is wrong. d3.easeCubic(0.25) will give you 0.0625:
var easy = d3.easeCubic(0.25);
console.log(easy);
<script src="https://d3js.org/d3.v4.min.js"></script>
Now, back to your question:
How can we reverse that, how can we find x given known y?
There is no native solution, but we can create our own function to find X given a known Y. The problem, of course, is that we have to invert the math for each specific easing... But, since you asked about d3.easeCubic, which is the same of d3.easeCubicInOut, let's try to create an inverted function for that particular easing.
First step, let's have a look at the source code:
export function cubicInOut(t) {
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}
You can easily see that this is the correct function, giving us the same value as the first snippet:
function cubicInOut(t) {
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}
console.log(cubicInOut(0.25))
Now, let's try to invert it.
The math here is somehow complicated, but for values less than 1, here is the function:
function inverseEaseCubic(t){
return Math.cbrt(t * 2) / 2;
}
And here is the demo. We pass 0.0625 to the function, and it returns 0.25:
function inverseEaseCubic(t){
return Math.cbrt(t * 2) / 2;
}
console.log(inverseEaseCubic(0.0625))
If you want to deal with numbers bigger than 1, this is the complete function:
function InverseEaseCubic(t){
return t <= 1 ? Math.cbrt(t * 2) / 2 : (Math.cbrt(2 * t - 2) + 2) / 2;
}
PS: In his comment, #altocumulus just reminded us that, sometimes, it's even impossible to find the value. Here is a very simple example. Suppose this function:
function exponentiation(a){
return a*a;
}
Now imagine that, when called with an unknown argument, the function returned 4. What's the argument? Can we find out? Impossible to determine, because second degree equations, like this one, have 2 roots:
console.log(exponentiation(2))//returns 4
console.log(exponentiation(-2))//also returns 4
I used the #Gerardo Furtado answer but the inverse function didn't work well so I wrote another
function cubicInOut(t) {
return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}
function inverseEaseCubic(x) {
return x < .5 ? Math.cbrt(x / 4) : (2 - Math.cbrt(2 - 2 * x)) / 2;
}
console.log(inverseEaseCubic(cubicInOut(1)) === 1);
console.log(inverseEaseCubic(cubicInOut(0.6)) === 0.6);
console.log(inverseEaseCubic(cubicInOut(0.4)) === 0.4);
console.log(inverseEaseCubic(cubicInOut(0.1)) === 0.1);
console.log(inverseEaseCubic(cubicInOut(0)) === 0);
I'm trying to make a projectile calculator, so it really need to change the way to calculate again & again until it is done.
but now i'm facing with a problem..again :(
var Height = Number(document.getElementById("Height").value);
var Velocity = Number(document.getElementById("Velocity").value);
var Range = Number(document.getElementById("Range").value);
var First = ((((Math.SQRT2 * Velocity) + (Math.sqrt(19.6) * Velocity * Height)) * Math.cos(0.785398163)) / 9.8);
document.getElementById("First").innerHTML = First;
if(First < Range)
document.getElementById("show").innerHTML = "Need more velocity to success on this range";
else
{
for(var i = -1.570796327; [>>>****HELP****<<<] ; i+0.000000001)
{
((((Velocity * Math.sin(i)) + Math.sqrt(Velocity * Math.sin(i) * Velocity * Math.sin(i) - 19.6 * Height))) / 9.8) * Velocity * Math.cos(i))
}
}
ALL of this code is make for finding a correct angle for projectile shooting, and I use "i" for angle
Please look on [**HELP**] that's the problem...I want to stop this loop after my calculation is equal to "Range" but I really have no idea to do that :(
After I got the correct "i" how can i print it to show the answer?
or anyways to make this code better or faster calculation?
Ty for every help :)
You could use break to exit the loop if you reached the expected value/range. You may also check if your result is near your range within +/- a value because you probably won't get the exact same values as you defined for Range.
for(var i = -1.570796327; i < MaxValue ; i+0.000000001)
{
result = ((((Velocity * Math.sin(i)) + Math.sqrt(Velocity * Math.sin(i) * Velocity * Math.sin(i) - 19.6 * Height))) / 9.8) * Velocity * Math.cos(i));
if(result >= Range) break;
}
Use this where you want to break
if "condition fullfilled inside for-loop"
return false;
To print it why not use:
console.log(i);
In jquery and js, if you are using loops (for, while, $.each) than return true will be equal to continue in PHP, and return false will be equal to break. Since you are using simple for loop, than there is enough to use return false to break this loop.
Use Case
I am learning functional programming. During this exercise, I wanted to create a function that naturally overflows. As an example, if the range of the data is from 2-12, if the value of the input is 12 and you add 1 to it, it becomes 2. Likewise, if you subtract 1 from 2, it becomes 12. It should be noted that I want to improve my math skills because I haven't been thinking like a mathematician for the past 15 years. So forgive me if this looks fairly trivial.
Implementation
The first implementation was the following:
var confineRange(value, min, max) {
var newValue = value;
while (newValue > max) {
newValue -= max;
}
while (newValue < min) {
newValue = max - (min - newValue);
}
return newValue;
}
Fiddle Here
This implementation worked, but seeing a loop, meant that it could be improved. So the second version I attempted was this:
function confineRange(value, min, max) {
if (value > 0)
return (value % max - min)
if (value < 0)
return ((value + max) % max) - min
if (value == 0)
return max - min;
}
However, this version looks like it could be simplified even more.
Questions
How could this be encapsulate in a single mathematical function?
Would it be possible to create this function using bit-shifting? If so, how?
Is there a more elegant solution using native javascript functions?
First for simplicity let's see for positive integers only, assuming that the max > min relation of the parameters are met, and value is larger or equal to min:
function confineRange(value, min, max) {
return ((value - min) % (max - min + 1)) + min;
}
The bottom end of your range is min, and you want to confine within a max - min + 1 range. For example with your example of min = 2 and max = 12 the result can get 11 distinct values! (And not 10 like it may seem first).
Let's test it with the edge cases:
confineRange(2, 2, 12);
This will execute ((2 - 2) % (12 - 2 + 1)) + 2, which results 2, good.
confineRange(12, 2, 12);
This will execute ((12 - 2) % (12 - 2 + 1)) + 2, which results 12, also good. Note that 12 - 2 makes 10, which is the largest integer which will pass through % 11 unmodified. Now let's try with 13:
confineRange(13, 2, 12);
Now after partially calculating it, it will look like (11 % 11) + 2, which will make 2 as expected (that is if that 13 was reached as 12 + 1, then it will seem to properly wrap around to 2).
So the basic idea is this.
The function however might fail with numbers below 2 due to how Javascript may or may not handle negative numbers, for example see this article. I don't know whether the behaviour is standardized or particular browsers may or may not try to fix it, so better assume this undefined.
The problem now is that you have no possibility of feeding negative numbers in the '%' operator, but given this interface you can only solve the problem with '%' (modulo). So an other method has to be employed.
JavaScript has a Math.floor() function which always rounds downwards (check it here). Using this can eliminate the problem of negatives, so let's construct our own modulo from it:
function confineRange(value, min, max) {
t = value - min;
d = max - min + 1;
t = t - (Math.floor(t / d) * d);
return t + min;
}
The modulo happens on the third (t = t - (Math.floor(t / d) * d);) line, this calculates t % d independent of sign. This solution will work properly for numbers below 2 as well, so you will for example get 12 if you supply 1 as value with your example.
For your second question the problem is solvable with bit manipulation, but only if the range (the number of distinct values you want to get) is a power of 2. This case applying a proper AND (&) mask on the value will do the job.
Lets say I have a list of numbers in the following form(Ignore the | they are there for formating help).
00|00|xx
00|xx|00
xx|00|00
etc.
Rules: XX can be any number between 1 and 50. No XX values can be identical.
Now I select a random set of numbers(no duplicates) from a list qualifying the above format, and randomly add and subtract them. For example
000011 - 002400 - 230000 = -232389
How can I determine the original numbers and if they were added or subtracted solely from -232389? I'm stumped.
Thanks!
EDIT:
I was looking for a function so I ended up having to make one. Its just a proof of concept function so variables names are ugly http://jsfiddle.net/jPW8A/.
There are bugs in the following implementation, and it fails to work in a dozen of scenarios. Check the selected answer below.
function reverse_add_subtract(num){
var nums = [];
while(num != 0){
var str = num.toString(),
L = Math.abs(num).toString().length,
MA = str.match(/^(-?[0-9]?[0-9])([0-9][0-9])([0-9][0-9])*$/);
if(MA){
var num1 = MA[1],
num2 = MA[2];
}else{
var num1 = num,
num2 = 0;
}
if(L%2)L++;
if( num2 > 50){
if(num < 0) num1--;
else num1++;
}
nums.push(num1);
var add = parseInt(num1 + Array(--L).join(0),10);
num = (num-add);
}
return nums;
}
reverse_add_subtract(-122436);
First note that each xx group is constrained from [1, 50). This implies that each associated pair in the number that is in the range [50, 99) is really 100 - xx and this means that it "borrowed from" the group to the left. (It also means that there is only one set of normalized numbers and one solution, if any.)
So given the input 23|23|89 (the initial xx spots from -232389), normalize it -- that is, starting from the right, if the value is >= 50, get 100 - value and carry the 100 rightward (must balance). Example: (23 * 100) + 89 = 2300 * 89 = 2400 - 11 = 2389. And example that shows that it doesn't matter if it's negative as the only things that change is the signs: (-23 * 100) - 89 = -2300 - 89 = -2400 + 11 = -2389
(Notes: Remember, 1 is added to the 23 group to make it 24: the sign of the groups is not actually considered in this step, the math is just to show an example that it's okay to do! It may be possible to use this step to determine the sign and avoid extra math below, but this solution just tries to find the candidate numbers at this step. If there are any repeats of the number groups after this step then there is no solution; otherwise a solution exists.)
The candidate numbers after the normalization are then 23|24|11 (let's say this is aa|bb|cc, for below). All the xx values are now known and it is just a matter of finding the combination such that e * (aa * 10000) + f * (bb * 100) + g * (cc * 1) = -232389. The values aa, bb, cc are known from above and e, f, and g will be either 1 or -1, respectively.
Solution Warning: A method of finding the addition or subtraction given the determined numbers (determined above) is provided below the horizontal separator. Take a break and reflect on the above sections before deciding if the extra "hints" are required.
This can then be solved by utilizing the fact that all the xx groups are not dependent after the normalization. (At each step, try to make the input number for the next step approach zero.)
Example:
-232389 + (23 * 10000) = -2389 (e is -1 because that undoes the + we just did)
-2389 + (24 * 100) = 11 (likewise, f is -1)
11 - (11 * 1) = 0 (0 = win! g is 1 and solution is (-1 * 23 * 10000) + (-1 * 24 * 100) + (1 * 11 * 1) = -232389)
Happy homeworking.
First, your math is wrong. Your leading zeros are converting the first two numbers to octal. If that is the intent, the rest of this post doesn't exactly apply but may be able to be adapted.
11-2400-230000 = -232389
Now the last number is easy, it's always the first two digits, 23 in this case. Remove that:
-232389 + 230000 = -2389
Your 2nd number is the next 100 below this, -2400 in this case. And your final number is simply:
-2389 + 2400 = 11
Aww! Someone posted an answer saying "brute force it" that I was about to respond to with:
function find(num){for(var i=1;i<50;i++){for(var o1=0;o1<2;o1++){for(var j=1;j<50;j++){for(var o2=0;o2<2;o2++){for(var k=1;k<50;k++){var eq;if(eval(eq=(i+(o1?'+':'-')+j+'00'+(o2?'+':'-')+k+'0000'))==num){ return eq; }}}}}}}
they deleted it... :(
It was going to go in the comment, but here's a cleaner format:
function find(num){
for(var i=1;i<50;i++){
for(var o1=0;o1<2;o1++){
for(var j=1;j<50;j++){
for(var o2=0;o2<2;o2++){
for(var k=1;k<50;k++){
var eq;
if(eval(eq=(i+(o1?'+':'-')+j+'00'+(o2?'+':'-')+k+'0000'))==num){ return eq; }
}
}
}
}
}
}