Summing a number recursively and displaying it [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I searched for a solution to this problem quite a bit, but couldn't reach a solution. Would be great if someone can point me in the right direction.
Ok, so suppose there's a number :-
0.001
What I want to do is, add 0.001 (the same number) to it again and again ever second and also display the change dynamically.
So :-
second 1 :- 0.001
second 2:- 0.002
second 3 :- 0.003
This has to keep running for 1 hour and I should be able to see it's value changing dynamically on my web page. How can I achieve this? I did quite a research on using countup.js, but no result. I thought of a solution to use ajax, but this would cause a lot of load.
Whats the best that I can do here?

You can also try this
<div id="display"></div>
var number = 1;
var timer = function(){
number++;
document.getElementById('display').innerHTML = parseFloat(number / 1000);
if(number < 3600){ // 1 hour check
setTimeout(timer,1000);
}
};
timer();

simple with js
var value = 0.001; //value to start
var inc = 0.001; //increment
var end = 0.010; //to test , 1 hour is 3.600
var _interval = setInterval(function() {
document.getElementById('midiv').innerHTML = value;
value += inc;
value = parseFloat(value.toFixed(3));
if (value > end) {
clearInterval(_interval);
}
}, 1000);
<div id="midiv">
</div>

Here is an example using rxjs
var interval = 1000;
var totrun = 60*1000
var v = 0
const source = Rx.Observable
.interval(interval)
.takeUntil(Rx.Observable.timer(totrun));
const subscription = source.subscribe(
t => {
v=v+0.001
$('#v').html(v);
},
err => console.log('Error: ' + err),
() => console.log('Completed'));

Is this what you want?
feel free to play with it
var c = 0.000;
var count = document.getElementById('count');
count.innerHTML = c;
// Creates the interval with the name interval
var interval = setInterval(function() {
c += 0.001
count.innerHTML = c;
// Its possible that you will see 0.00300000000007 artifacts
// You can fix it by converting it to a string and showing only a part
// count.innerHTML = ("" + c).substring(0, 5);
}, 100) // 1/10 sec for demo
// Clear the interval after one hour
setTimeout(function() {
clearInterval(interval)
}, 1000) // one second for demo
counter: <span id="count"></span>

var interval = setInterval(function(){
var old = parseFloat($(".number").html());
var newValue = old + 0.001;
$(".number").html(newValue);
}, 1000);
// this clears the interval loop from firing after 1 hour
setTimeout(function(){
clearInterval(interval);
}, 3600000)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="number">0.001</div>
That should do the trick

Related

Increment value in time

I am looking to increment the value of "time" with 0.01 each 10 miliseconds until it gets to the desired value. Right now it just increases it instantly to the conditioned value.
var time = 0;
function animate() {
decreaseIncrement = -0.78;
increaseIncrement = 0.78;
if (
(document.getElementById("but5").onclick = function () {
if (time < increaseIncrement) {
do {
time += 0.01;
} while (time < increaseIncrement);
}
})
)
if (
(document.getElementById("but3").onclick = function () {
if (decreaseIncrement < time) {
do {
time -= 0.01;
} while (decreaseIncrement < time);
}
})
)
increaseIncrement = time + increaseIncrement;
decreaseIncrement = time + decreaseIncrement;
}
https://jsfiddle.net/2epqg1wc/1/
You can solve that problem using setInterval which repeatedly runs a task every x milliseconds until you cancel it. Below code reduces the value to 0 in 0.01 steps with a step performed every 10 milliseconds.
var value = 1.0;
var decrement = 0.01;
function decreaseAnimation() {
var interval = setInterval(() => {
value -= decrement;
console.log(value);
if (value <= 0) {
clearInterval(interval);
}
}, 10);
}
decreaseAnimation();
You have 3 options:
requestAnimationFrame (rAF)
setTimeout/setInterval (sTo)
messageChannel
The first 2 options are more straightforward but they will lack the precision, because rAF fires every 17 milliseconds (assuming 60Hz) and sTO will fire at most 4ms after 4 successive recursions. Usually rAF is preferred over sTo because of better reliability in timing of firing these callbacks. Use sTO as a fallback if rAF is not supported.
Here is an implementation from a library for similar purposes:
var rafx = require("rafx");
rafx.async({ //create a ledger object to store values
curr_time:0,
desired:Math.random(),
frames:0
}).animate(function(obj){
//obj is the ledger above
//increment obj.frames here if you want to
return obj;
},).until(function(obj){
obj.frames++;
obj.curr_time = obj.frames * 17 / 10 * 0.01;
return obj.curr_time >= obj.desired;
}).then(function(obj){
console.log("sequence ended with values:" + JSON.stringify(obj));
});
You can copy paste the code above here and test it.
The last option uses MessageChannel to post message between ports, which gives extremely high precision because it is fired at the next event loop. You can combine this with performance.now to determine whether to increment your time or not.
Disclosure: I am the author of the aforementioned lib.

Increment to a value from 0 in 5 seconds

I need to increment the value from 0 to 103551 in 5 seconds. Below is the logic I have used. But it's not incrementing to the required value within 5 secs
var counter = 0;
var el = document.getElementById('seconds-counter');
function incrementSeconds() {
counter += 1;
el.innerText = "Processing " + counter + " execution records";
if(counter == 103551) {
console.log(new Date());
}
}
console.log(new Date());
var time = 103551/5000;
var cancel = setInterval(incrementSeconds, time);
HTML
<div id='seconds-counter'> </div>
Your math is a little off. 103551/5000 = 20.7102ms
1000ms = 1s, 5s = 5000ms, 5000/20.7102 = 240 iterations.
The equation you want to solve is 5000/x = numIterations
So x = 5000/numIterations
Note: Most browsers have a minimum number you can set in setInterval(), so you may need to increment by more than 1 each loop to count to 103551 in 5 seconds. Since this is an oddly specific problem I'm going to gues that this might be an assignment so will omit a full solution from this answer. Good luck!

countdown from n to 0 in given time, negative end value

I am working on simple script that should animate given value (for example 6345.23) to 0 by counting it down, it should also end up at 0 if specified amount of time have passed (for example 2 seconds.
I started by simple logic:
given config: initial value, time in sec, interval
time is given in seconds so convert it to milliseconds
calculate amount of ticks by dividing time in ms by interval
calculate amount of decreased value per tick by dividing initial value by amount of ticks
once above are known we can simply do: (simple model, not actual code)
intId = setInterval(function() {
if(ticks_made === amount_of_ticks) {
clearInterval(intId);
} else {
value -= amount_per_tick;
// update view
}
}, interval);
actual code:
var value = 212.45,
time = 2, // in seconds
interval = 20; // in milliseconds
var time_to_ms = time * 1000,
amount_of_ticks = time_to_ms / interval,
amount_per_tick = (value / amount_of_ticks).toFixed(5);
var start_time = new Date();
var ticks_made = 0;
var intId = setInterval(function() {
if(ticks_made === amount_of_ticks) {
console.log('start time', start_time);
console.log('end time', new Date());
console.log('total ticks: ', amount_of_ticks, 'decresed by tick: ', amount_per_tick);
clearInterval(intId);
} else {
value = (value - amount_per_tick).toFixed(5);
console.log('running', ticks_made, value);
}
ticks_made++;
}, interval);
Link do fiddle (in console you can observe how it works)
If you set time to 2 (2 seconds) its ok, but if you set time to for example 2.55 (2.55 seconds) it doesnt stop at all at 0, its passing by and going indefinitely in negative values.
How i can fix it so no matter what is set in seconds its always go precisly one by one until reaches perfectly 0?
var value = 212.45,
time = 2, // in seconds
interval = 20; // in milliseconds
var time_to_ms = time * 1000,
amount_of_ticks = time_to_ms / interval,
amount_per_tick = (value / amount_of_ticks).toFixed(5);
var start_time = new Date();
var ticks_made = 0;
var intId = setInterval(function() {
if(ticks_made === amount_of_ticks) {
console.log('start time', start_time);
console.log('end time', new Date());
console.log('total ticks: ', amount_of_ticks, 'decresed by tick: ', amount_per_tick);
clearInterval(intId);
} else {
value = (value - amount_per_tick).toFixed(5);
console.log('running', ticks_made, value);
}
ticks_made++;
}, interval);
You're relying on ticks_made === amount_of_ticks being an exact match. Chances are, due to rounding, you won't get an exact match, so you'd be better off doing:
if(ticks_made >= amount_of_ticks) {
kshetline's answer correctly addresses why you get into negative values. When dealing with fractional IEEE-754 double-precision binary numbers (in the normal range, or even whole numbers in very high ranges), == and === can be problematic (for instance, 0.1 + 0.2 == 0.3 is false). Dealing with values as small as the fractional values here are, accumulated imprecision is also a factor. It's inevitable to have to fudge the final step.
But there's a larger issue: You can't rely on timers firing on a precise schedule. Many, many things can prevent their doing so — other UI rendering work, other scripts, CPU load, the tab being inactive, etc.
Instead, the fundamental technique for animation on browsers is:
Update when you can
Update based on where you should be in the animation based on time, not based on how many times you've animated
Use requestAnimationFrame so your update synchronizes with the browser's refresh
Here's your code updated to do that, see comments:
// Tell in-snippet console to keep all lines (rather than limiting to 50)
console.config({maxEntries: Infinity});
var value = 212.45,
time = 2.55, // in seconds
time_in_ms = time * 1000,
amount_per_ms = value / time_in_ms,
interval = 100 / 6, // in milliseconds, ~16.66ms is a better fit for browser's natural refresh than 20ms
ticks_made = 0;
// A precise way to get relative milliseconds timings
var now = typeof performance !== "undefined" && performance.now
? performance.now.bind(performance)
: Date.now.bind(Date);
// Remember when we started
var started = now();
// Because of the delay between the interval timer and requestAnimationFrame,
// we need to flag when we're done
var done = false;
// Use the interval to request rendering on the next frame
var intId = setInterval(function() {
requestAnimationFrame(render);
}, interval);
// About half-way in, an artificial 200ms delay outside your control interrupts things
setTimeout(function() {
console.log("************DELAY************");
var stop = now() + 200;
while (now() < stop) {
// Busy-loop, preventing anything else from happening
}
}, time_in_ms / 2);
// Our "render" function (okay, so we just call console.log in this example, but
// in your real code you'd be doing a DOM update)
function render() {
if (done) {
return;
}
++ticks_made;
var elapsed = now() - started;
if (elapsed >= time_in_ms) {
console.log(ticks_made, "done");
done = true;
clearInterval(intId);
} else {
var current_value = value - (amount_per_ms * elapsed);
console.log(ticks_made, current_value);
}
}
/* Maximize in-snippet console */
.as-console-wrapper {
max-height: 100% !important;
}
If you run that, then scroll up to the "************DELAY************" line, you'll see that even though rendering was held up by "another process", we continue with the appropriate next value to render.
It would make sense to convert the result of .toFixed() to a number right away:
let amount_per_tick = +(value / amount_of_ticks).toFixed(5);
let value = +(value - amount_per_tick).toFixed(5);
(note the + signs)
Then you will never have to worry about type coercion or anything, and instead just focus on math.

while loop not working in javascript [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm having a bit of trouble getting this code to work. I think it has something to do with the while loop. Also I'm new to JavaScript so, if you any suggestions on ways to improve the syntax or make my code more efficient it would be greatly appreciated.
how the code should work.
The user enters a cost of an item and then the amount of
money given. The program will figure out the change and the number of quarters, dimes, nickels, pennies needed for the change.
what happens when run
the two prompt boxes pop up and than I get a alert warning..
"A script on this page may be busy, or it may have stopped responding. You can stop the script now, open the script in the debugger, or let the script continue."
https://jsfiddle.net/krighty78/g44ejnbw/1/
/* The user enters a cost of an item and then the amount of
money given. The program will figure out the change and the number of quarters, dimes, nickels, pennies needed for the change.*/
var cost = prompt('please enter total cost of the item without tax');
cost = parseFloat(cost);
var moneyGiven = prompt('please enter the amount of money given');
moneyGiven = parseFloat(moneyGiven);
var tax = 0.15;
tax = (cost * tax);
var quarter = 0;
var dime = 0;
var nickel = 0;
var penny = 0;
var q = 0.25;
var d = 0.10;
var n = 0.05;
var p = 0.01;
var change = (moneyGiven - (cost + tax));
console.log(change);
while (change > 0) {
if (change >= q) {
change - q;
quarter++;
} else if (change >= d) {
change - d;
dime++;
} else if (change >= n) {
change - n;
nickel++;
} else if (change >= p) {
change - p;
penny++;
}
}; //while loop
console.log(quarter);
console.log(dime);
console.log(nickel);
console.log(penny);
The while loop is OK, the problem is in the statements
change - q;
change - d;
change - n;
change - p;
You are not updating the value of change. Change these to:
change = change - q;
change = change - d;
change = change - n;
change = change - p;

Curve speed down using Math.PI

I am trying to create a countdown that starts at 100 and ends at 30.
I want the beginning of the countdown to be really fast and then slow down and stop at 30. At the moment though the "path" of the countdown is linear.
Also to make you aware, the start number and end number may change, but still require a curved time effect.
https://jsfiddle.net/ygnvav7c/
$(document).ready(function() {
var timer;
var count=100;
var ms = 1;
var step = 5;
var counter = setTimeout(timer, ms);
Countdown();
function Countdown() {
count=count - 1;
if (count >= 30) {
$('#countdown-display').html(count);
ms = ms + step;
counter = setTimeout(Countdown, ms);
}
}
});
How can I use Math.PI to make the time "curve"?
Parameterize your count variable with some number 0 <= t <= 1. Increment this with a regular interval (say 0.01)
e.g. for a quadratic decay:
count = count_start + (count_end - count_start) * (1 - t) ^ 2
For a sine-curve decay:
count = count_start + (count_end - count_start) * sin(pi * t / 2)
For an exponential decay:
count = count_start + (count_end - count_start) * (1 - k ^ t) / (1 - 1 / k)
where k > 1
As much as I appreciate the solutions of my dear collegues but the requirement was that it stops at the end. So the time must go to infinite or at least close enough.
Taking 10^6 as "close enough" and the tangent function as the means to reach infinity (but not to go beyond) together with a bit of simple algebra and taking the liberty to change the counting function from decreasing to increasing we get the following to play with-not to to forget the complete ignorance of teh good ol' Chicago Manual of Style by using an infamously long and winded run-on sentence, that is additionally peppered with a lot of redundant additions.
tl;dr: We need to get the x in tan(x) as close to PI/2 as possible but not bigger to reach that goal.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Counter</title>
<script type="text/javascript">
var timer;
var counter = setTimeout(timer, ms);
var ms = 1;
var count_start = 30;
var count_end = 100;
var count = count_start;
// roughly (atan(10^6) - .02) / 68
var step = 0.0228058;
// to avoid zero
var start = 0.02;
var brk = document.createElement("br");
function Countdown() {
var out = document.getElementById("output");
var text;
if (++count < count_end) {
start += step;
ms = Math.tan(start) * count;
counter = setTimeout(Countdown, ms);
text = count.toString() + " - " + ms.toString();
text = document.createTextNode(text);
out.appendChild(text);
out.appendChild(brk.cloneNode());
}
}
</script>
</head>
<body onload="Countdown()">
<p id="output" > </p>
</body>
</html>
Reducing the value in step makes the curve end earlier (you kind of "zoom in"), e.g.: step = 0.02 lets the final step last about half a second and about 85ms with step = 0.01.

Categories