javascript recursive function returns initial value - javascript

Please, help needed!
I'm trying to make a small js compounding calculator
function calculateCompound(amount, earning, remains, roi, compound) {
if (remains > 0) {
var ini_earning = earning;
var accrual = amount * roi;
earning = accrual * (1 - compound);
var new_amount = amount + accrual - earning;
var new_earning = ini_earning + earning;
remains--;
calculateCompound(new_amount, new_earning, remains, roi, compound);
}
return earning + amount;
}
calculateCompound(100, 0, 5, .1, .5);
but after 5 calls it returns the initial values (105 in this case)
Many thanks in advance!

The you never return the value from your recursion call, this is why it returns the initial value.
The idea is to have a base case which returns earning + amount
And recur by returning the calculateCompound call value
function calculateCompound(amount, earning, remains, roi, compound) {
if (remains <= 0) {
return earning + amount;
}
var ini_earning = earning;
var accrual = amount * roi;
earning = accrual * (1 - compound);
var new_amount = amount + accrual - earning;
var new_earning = ini_earning + earning;
return calculateCompound(new_amount, new_earning, remains - 1, roi, compound);
}

Related

How to make a list of numbers that perfectly divide with 6000 or the most approach to 6000

I need to Make an program that calculate the perfect way of cut bars of 6000milimeters to Make indoor doors and Windows and i need to waste less I can everytime I cut there ia 2 mm that is wasted because of blade. So for example i Have this inputs: 2x1450 2x1600 3x1004 And neeed to show me how can i sort to give me perfect 6000 or the most aproach for example cut 1600+2x1450 And the next one cut 1600+3x1004 with 2 mm cut error at every input.So IT s like sort every inputs in grids of 6000mm.
function bign(){
var bignumber;
var nr1;
var nr2;
var nr3;
var bara = 6000;
var nrbuc1;
var nrbuc2;
var nrbuc3;
var bucx1;
var bucx2;
var bucx3;
nr1=parseInt(document.getElementById("no1").value)
nrbuc1=parseInt(document.getElementById("buc1").value);
nr2=parseInt(document.getElementById("no2").value);
nrbuc2=parseInt(document.getElementById("buc2").value)
nr3=parseInt(document.getElementById("no3").value);
nrbuc3=parseInt(document.getElementById("buc3").value)
bucx1=nr1 * nrbuc1;
bucx2=nr2 * nrbuc2;
bucx3=nr3 * nrbuc3; '
var total1 = bucx1+bucx2;
var total2 = bucx2+bucx3;
var total3 = bucx1+bucx2+bucx3;
var rezultat1= document.getElementById("VERIFICAT").innerHTML = nr1 + " plus " + nr2 + " result";
var rezultat2= document.getElementById("VERIFICAT").innerHTML = nr2 + " plus " + nr3 + " rusult";
var rezultat3= document.getElementById("VERIFICAT").innerHTML = nr1 + " plus " + nr2 + " plus" + nr3;
var gresit = document.getElementById("VERIFICAT").innerHTML = "GRESIT";
if (total1 % bara == 0){
alert (rezultat1);
}
if (total2 % bara == 0){
alert (rezultat2);
}
if (total3 % bara == 0){
alert (rezultat3);
}
else (total1%bara != 0 || total2%bara != 0 || total3%bara !=0 )
alert(gresit);
}
Details are commented in example
/**
* Given a constant width and one or more smaller
* widths, find how many of the smaller widths can
* be combined to get as close as possible to the
* constant width (but not exceed it)
* #param {number} sheet - The width limit that
* cannot be exceeded
* #param {rest<string>} ...points - The points to
* to cut widths to.
*/
class Chop {
constructor(sheet, ...points) {
this.sheet = sheet;
this.points = [...points];
}
/**
* A utility method that formats text
* #param {any} data - Any input a JSON can handle
* #param {boolean} noConsole - Determine whether
* data is to display in console or
* returned. #default is false
* #return {any} any output a JSON can handle
*/
static log(data, noConsole = false) {
if (noConsole) {
return JSON.stringify(data).trim();
}
console.log(JSON.stringify(data));
}
/**
* Given an array of number-strings, convert them
* into a simple format. Each formatted number is
* a width to be "cut"
* # return {array} - An array of numbers used to
* cut the widths
*/
mark() {
this.points = this.points.flatMap(str => {
/**
* If a string has a space...
* ...split the string at every space
*/
if (str.includes(' ')) {
let y = str.split(' ');
y[0] = +y[0] + 2;
y[1] = +y[1] + 2;
return y;
}
/**
* If a string has a "x"...
* ...split string at every "x"...
* ...each number to the left of "x" determines...
* ...how many times the number on the right of "x" is
* repeated
*/
if (str.includes('x')) {
let x = str.split('x');
x.splice(-1, 1, ' ' + (+x[1] + 2));
return x[1]
.repeat(x[0])
.split(' ')
.map(n => +n);
}
return (parseInt(str) + 2);
});
let order = this.points.sort((a, b) => a - b);
Chop.log(order);
return order;
}
/**
* Separates the numbers that fit within the limit
* and those that don't.
* #return {array<array>} - An array of arrays
*/
cut() {
let sum = 0, cutoff, index;
for (const [idx, num] of this.points.entries()) {
if (num + sum > this.sheet) {
cutoff = `Cutoff is ${num}mm at index: ${idx}`;
index = idx;
break;
} else {
sum = num + sum;
}
}
let done = this.points.slice(0, index);
let notDone = this.points.slice(index);
Chop.log(
`Sum of cut sections: ${sum}mm
${cutoff}`);
return [done, notDone];
}
}
let z = new Chop(6000, '2x1140', '1000', '3x500', '3000 5000');
Chop.log(z.mark());
Chop.log(z.cut());

Why is this easeOutCubic returning larger jumps in change at the beginning and smaller at the end?

I think i'm using this easing function wrong. Ease out functions should return larger changes to start, but I'm getting bigger jumps towards the end:
//Current value = Change
25 = 0
27.227575000000005 = 2.227575000000005
31.63817500000001 = 4.410600000000006
38.187700000000014 = 6.549525000000003
46.83250000000002 = 8.644800000000004
57.52937500000003 = 10.696875000000013
70.23557500000004 = 12.70620000000001
84.90880000000004 = 14.673225000000002
101.50720000000004 = 16.598399999999998
What am i doing wrong?
What I want:
It should start at 25 (25%, but I use the integer 25)
It should end at 100 (it's ok that it goes over as I'll limit it to 100 max)
It should start fast and end slow
https://jsfiddle.net/pqLddvzo/1/
function easeOutCubic(t, b, c, d) {
t /= d;
t--;
return c*(t*t*t + 1) + b;
}
var x = 25;
var i = 0;
while ( x < 100 && i < 500 )
{
let last = x;
//Calculate our new percentage
x = easeOutCubic( i, x, 75, 100 )
//The new value and the change in value
console.log( x + " = " + ( x - last ) );
//move to next step
i++;
}
//Also, why doesn't it take the full number of steps?
console.log( i );
You probably want something with Math.sqrt()
// Given a scale function that accepts whatever and return a number between 0 and 1
// Returns a function that accepts the same whatever and returns a number between min and max
function mapScale(scale, min, max) {
return (...args) => {
const original = scale(...args);
return min + (original * (max - min));
};
}
// Accepts a number between 0 and 1
// Returns a mapped number between 0 and 1
function sqrtScale(n) {
n = Math.min(1, Math.max(n, 0)); // stay within the borders of 0 and 1
return Math.sqrt(n);
}
const sqrtScaleBetween25And100 = mapScale(sqrtScale, 25, 100);
for (let i = 0; i < 1; i = i + .1) {
console.log(sqrtScaleBetween25And100(i));
}
Note how the first 5 make up 50 units, and the last 5 only 25. You can make a steeper curve by applying a stronger root, for instance, n ** (1/3) or event Math.sqrt(Math.sqrt(n))
The issue is that I was passing the value returned back into the next call as the "original" value:
x = easeOutCubic( i, x, 75, 100 );
Instead it should be:
x = easeOutCubic( i, 25, 75, 100 )
That field needs to remain unchanged. Only the first parameter should change on each call.

Generate random number between range including negative in javascript

I am trying to set a function that creates a random number between a range
I need to make it working with negative values so I can do
randomBetweenRange( 10, 20)
randomBetweenRange(-10, 10)
randomBetweenRange(-20, -10)
This is what I am trying, it is a bit confusing and at the moment randomBetweenRange(-20, -10) is not working..
function randomBetweenRange(a, b){
var neg;
var pos;
if(a < 0){
neg = Math.abs(a) + 1;
pos = (b * 2) - 1;
}else{
neg = -Math.abs(a) + 1;
var pos = b;
}
var includeZero = true;
var result;
do result = Math.ceil(Math.random() * (pos + neg)) - neg;
while (includeZero === false && result === 0);
return result;
}
How can I make it working?
ASSUMING you will always have the little value on first, this code will do the tricks, see the comment below and don't hesitate to ask !
var a=parseInt(prompt("First value"));
var b=parseInt(prompt("Second value"));
var result = 0;
// Here, b - a will get the interval for any pos+neg value.
result = Math.floor(Math.random() * (b - a)) + a;
/* First case is we got two neg value
* We make the little one pos to get the intervale
* Due to this, we use - a to set the start
*/
if(a < 0) {
if(b < 0) {
a = Math.abs(a);
result = Math.floor(Math.random() * (a + b)) - a;
}
/* Second case is we got two neg value
* We make the little one neg to get the intervale
* Due to this, we use - a to set the start
*/
} else {
if(b > 0) {
a = a*-1;
result = Math.floor(Math.random() * (a + b)) - a;
}
}
console.log("A : "+a+" | B : "+b+" | Int : "+(a+b)+"/"+Math.abs((a-b)));
console.log(result);
You have declared the variable 'pos' in the beginning itself. Then why do you declare it in the 'else' part? ( var pos = b;)
Hence, for this statement,
do result = Math.ceil(Math.random() * (pos + neg)) - neg;
'pos' will not have any value.
do result = Math.ceil(Math.random() * (pos + neg)) - neg;
Specifically Math.random() * (pos + neg) returns the wrong range. If pos = -20 and neg = -30, the range between pos and neg should be 10, but your operation returns -50. You should also add one to the range because its technically the amount of possibilities (ex: if you want to generate your function to return {0,1}, the range between pos and neg is 1, but there are two possibilities of numbers to return) and subtract another 1 from result because you're using Math.ceil
Your else clause also redeclares var pos
If you want to generate a number between -50 and 50 - Get a random number between 0 and 100 then subtract 50
var randomNumber = Math.floor(Math.random() * 101) - 50;
console.log(randomNumber);

How to return a random number in javascript which is always greater then the previous number

How can I return a random number in javascript which is always greater then the previous random number every time the code reruns. For example when the code runs first time it returns 1000 and then when it runs second time it returns 1300.
Conditions: The number must always be an integer.
function randomFunction() {
var x = 0
return function() {
x = x + Math.round( Math.random() * 100 )
return x
}
}
var nextRandom = randomFunction()
nextRandom() // => 51
nextRandom() // => 127
nextRandom() // => 203
How about this?
function myRnd(prev, max) {
return prev + Math.floor(Math.random() * max) + 1;
}
var last;
last = myRnd(1000, 500);
last = myRnd(last, 500);
EDIT
Being inspired by #dimakura's outstanding answer, here is my closure-based function which accepts start value and next max random step:
function myRndFunc(baseValue) {
return function(max) {
baseValue += Math.floor(Math.random() * max) + 1;
return baseValue;
};
}
var myRnd = myRndFunc(1000);
myRnd(300);
myRnd(500);
How about simply adding the previous number?
Try this :
for (i = 0; i < n; i++) {
newR = Math.floor((Math.random() * 1000) + oldR);
// use newR here.
oldR = newR;
}
Conbine Math.random() with Math.floor() setting the minimum end of your range to the last result.
var min = 0;
var max = 10000;
$("#randomise").click(function() {
var result = Math.floor(Math.random() * (max - min)) + min;
$("#result").text(result);
min = result;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result"></div>
<button id="randomise">Randomise</button>

Generate incremented random numbers between 0 to 100 every second where new number should be greater than the previous nymber

I need a javascript where with every second call i get a random number between 0-100 where current number should be greater than previous number. I wrote a code to get random numbers every second but stuck at generating it with increment.
<script>
var span = document.getElementsByTagName("span")[3];
var i = 100;
(function randNumber() {
var a = Math.floor((Math.random() * i) + 1);
span.innerHTML = "RandNumber: " + a;
setTimeout( randNumber, 1000);
})();
Note : The numbers should generate randomly.
example result may be : 2,5,7,8,22,23,34,56,78,88.....
You should not create a new random number between zero and your maximum (i), but just between the last created number (lastNumber) and max (i).
Also you might want to stop, when the random numbers reached the maximum.
var span = document.getElementsByTagName("span")[3],
i = 100,
lastNumber = 0;
function randNumber() {
lastNumber = lastNumber + Math.floor( Math.random() * (i - lastNumber) + 1 );
span.innerHTML = lastNumber;
if( lastNumber < i ) {
setTimeout( randNumber, 1000 );
}
}
randNumber();
AS for the comments and the requirement of a minimum amount of steps until reaching the maximum:
In each iteration, just increase you number by a random value between 1 and ((max - min) / steps. It is pretty much the same code as above.
var span = document.getElementsByTagName("span")[3],
max = 100,
min = 0,
lastNumber = 0,
minSteps = 30;
// how wide can the average step be at most?
var stepWidth = (max - min) / minSteps;
function randNumber() {
lastNumber = lastNumber + Math.floor( Math.random() * stepWidth + 1 );
span.innerHTML = lastNumber;
if( lastNumber < max ) {
setTimeout( randNumber, 1000 );
}
}
randNumber();
If you extract the "between two numbers" logic into its own function like this, this becomes a lot easier. This way, you just generate a number between your last generated number and your maximum.
var max = 100
var last_number = 1
var interval_id = setInterval(function(){
last_number = get_random_number_greater_between(last_number, max)
span.innerHTML = "RandNumber: " + last_number;
if(last_number >= max){
window.clearInterval(interval_id)
}
}, 1000)
function get_random_number_greater_between(low, high){
return Math.floor(Math.random() * (high - low + 1) + low);
}
Try this:
// generate a random number from 0 to max - 1.
function rand(max) {
return Math.floor(max * Math.random());
}
// generate a random number from min to max.
function range(min, max) {
return min + rand(1 + max - min);
}
// the loop function
function next(n, callback) {
var m = range(n, 100);
if (m < 100) setTimeout(next, 1000, m + 1, callback);
callback(m);
}
var span = document.getElementById("rand");
next(0, function (m) {
span.innerHTML = "Random number: " + m;
});
<span id="rand"></span>

Categories