Timer stopping after 0.29 - javascript

<head>
<script>
window.setInterval(function(){timer()},100);
function timer()
{
document.getElementById("timer").innerHTML=
(parseInt(document.getElementById("timer").innerHTML*100)+1)/100;
}
</script>
</head>
<body>
<div id="timer">0.000</div>
</body>
As you see, timer counts only up to 0.29.
Why is it?

It's because of the way floating point math works coupled with your parseInt(). Refer to Is floating point math broken.
When it reaches 0.29, it does 0.29 x 100, which you're expecting to result in 29 but actually it is:
console.log(0.29 * 100);
28.999999999999996
Next, you convert it to an integer using parseInt() which results in 28 (removing all of the decimal places), finally you add 1 and divide by 100 making the result 0.29 and this is repeated on each tick of the timer, the number can't increase.
It would be better to store the raw value as a variable and output it using .toFixed(2), instead of using the number on the UI as the source. Like this:
Fiddle
var num = 0.00;
window.setInterval(function () {
timer();
}, 100);
function timer() {
num = ((num * 100) + 1) / 100;
document.getElementById("timer").innerHTML = num.toFixed(2);
}

Related

Every 1 second increase the value with a random number using decimal numbers

So I'm trying to increment the value of a number in an interval of 1 second with a decimal number between (0.01 and 0.05) and I can't seem to figure this out.
The only thing that it does is to show me numbers between 0.01 and 0.05 instead of adding them up to be an integer.
setInterval (function myFunction() {
var number = 0;
document.getElementById("computerScore").innerHTML = number +
Math.floor((Math.random() * 5) + 1)/100;
}, 1000)
<b>computer score:</b><p id="computerScore">0</p>
Your problem is that you are setting number to 0 in each execution, while it should be the current value.
You need to assign Number(document.getElementById("computerScore").textContent) to it, so it keeps updating with the added random number.
Note that I used textContent which is recommended here as it holds only the text content of the element avoiding HTML elements.
setInterval (function myFunction() {
var number = Number(document.getElementById("computerScore").textContent);
document.getElementById("computerScore").textContent= number +
Math.floor((Math.random() * 5) + 1)/100;
}, 1000)
Demo:
setInterval (function myFunction() {
var number = Number(document.getElementById("computerScore").textContent);
document.getElementById("computerScore").textContent = number +
Math.floor((Math.random() * 5) + 1)/100;
}, 1000)
<b>computer score:</b><p id="computerScore">0</p>
You need to retrieve the previous value from your score and add your random Number to it :
PS: I added .toFixed(2) to limit your result to two decimals.
let score = document.getElementById("computerScore");
setInterval (function myFunction() {
score.innerHTML = (+score.innerHTML + Math.floor((Math.random() * 5) + 1)/100).toFixed(2);
}, 1000)
<b>computer score:</b><p id="computerScore">0</p>
You set number to 0 every time you call the function, you should define number outside of the interval
var number = 0;
setInterval(function myFunction() {
document.getElementById("computerScore").innerHTML = number +
Math.floor((Math.random() * 5) + 1) / 100;
}, 1000)
You need to declare number outside the setTimeout:
var number = 0;
setInterval (function myFunction() {
number = number +
Math.floor((Math.random() * 5) + 1)/100;
document.getElementById("computerScore").innerHTML = number;
}, 1000)
JSFiddle
you can try something like this. You forgot to set the number to 0. Then you have to increment your number with the random value you're getting.
https://codepen.io/anon/pen/dgJpep
JS :
var number = 0;
function check(){
setInterval(function(){
number = number + Math.floor((Math.random() * 5) + 1)/100;
}, 3000);
}
check();
setInterval(function(){
document.getElementById('computerScore').innerHTML = number;
});
Let me know if it works for you !

jQuery count to number with duration between digits

What I am looking to do is have a number start counting either up or down, lets say from 1 to a 100 or a 100 to 1. I have found many many plugins that do this but they all have a duration variable. The problem is that duration variable applies to how long it takes to get from start to finish. I am looking for a way to set how long it takes to get to the next digit. IE counting from X to Y and updating the number every .25 seconds. This way a larger number would take longer to get to than a smaller number.
This plugin looks great but I can't get it to do what I want.
https://github.com/mhuggins/jquery-countTo
Any help would be great.
Please try this and let me know if that's what you want:
function countTo(min, max, interval, callback) {
var counter = min;
var i = setInterval(function() {
callback(counter);
counter++;
if(counter> max) return clearInterval(i);
}, interval*1000);
};
countTo(0, 100, 0.25, function(counter) {
$("#counter").text(counter);
});
countTo(0, 100, 0.01, function(counter) {
$("#counter2").text(counter);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="counter"> </div>
<div id="counter2"> </div>
You can try something like this
function count(target, start, end, step, timeInterval) {
var timer = setInterval(function() {
if (start == end) {
clearInterval(timer);
return false;
}
start += step;
target.html(start);
}, timeInterval);
}
count($('#timer1'), 1, 100, 1, 50);
count($('#timer2'), 100, 1, -1, 50);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="timer1"></div>
<div id="timer2"></div>

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.

Accurate floating point arithmetic in JavaScript

I am creating number spinner widget in JavaScript to essentially mimic the number field in webkit.
When you change the number, it needs to check to see if the value is not only within the accepted range, but also that it's in step:
<input type="number" min="0" max="100" step="1" />
If a user enters 5.5 the field will truncate this to the closest step lower than the value, which in this case is 5.
For a step of 2, if the user entered 5.5, the result would be 4.
The equation I was planning on using for this calculation looks like this:
...code...
_checkStep: function (val) {
val ret,
diff,
moddedDiff;
diff = val - this._min;
moddedDiff = diff % this._step;
ret = val - moddedDiff;
return ret;
},
//set elsewhere
_min,
_step,
...more code...
Although for testing purposes, you could simply use this:
function checkStep(val, min, step) {
var ret,
diff,
moddedDiff;
diff = val - min;
moddedDiff = diff % step;
ret = val - moddedDiff;
return ret;
}
This works great for integers and larger values, however I've run into issues with decimals due to how JavaScript handles floating point numbers.
For example:
checkStep(0.5, 0, 0.1) //returns 0.4, 0.5 is expected
In analyzing each line, it turns out that 0.5 % 0.1 in JavaScript returns 0.09999999999999998.
What can be done to make this function more accurate*?
*accurate being that it works for increments of 0.01 and up.
You could try making sure step is greater than 1 (by repeatedly multiplying by 10), then do your modulus, then scale back down to original. For example:
function checkStep(val, min, step) {
var ret,
diff,
moddedDiff;
var pows = 0;
while( step < 1 ) { // make sure step is > 1
step *= 10;
val *= 10;
min *= 10;
pows++;
}
diff = val - min;
moddedDiff = diff % step;
ret = val - moddedDiff;
return ret / Math.pow( 10, pows );
}
This works for the examples you provided, but I can't guarantee it will work for everything. See the jsfiddle here:
http://jsfiddle.net/bCTL6/2/
There's no absolutely guaranteed accurate floating point calculations. Use integer calculations instead. In your 0.1 example you can count amount of "0.1"'s in integers, visually adding point before last digit for user.

trim to 2 decimals

I have:
onclick="document.getElementById('field1').value =
Math.round((parseFloat(document.getElementById('field2').value,2)*100))/100 +
Math.round((parseFloat(document.getElementById('field3').value,2)*100))/100;"
Most numbers round ok to 2 decimal points which is what I need.
However, with an example like
onclick="document.getElementById('field1').value =
Math.round((parseFloat(document.getElementById('21.29').value,2)*100))/100 +
Math.round((parseFloat(document.getElementById('54.70').value,2)*100))/100;"
Field 1 is returning 75.99000000000001 How can I trim to 75.99 consistently?
var num = 5 / 6;
var display = num.toFixed(2)
num outputs: 0.8333333333333334
display outputs: "0.83"
How about this:
parseFloat(document.getElementById('21.29').toFixed(2));
The toFixed method should take care of the rounding nicely for you.
Use the method toFixed(2) to fix it at 2 decimal places:
(Math.round((parseFloat(document.getElementById('21.29').value,2)*100))/100 +
Math.round((parseFloat(document.getElementById('54.70').value,2)*100))/100).toFixed(2);
I had a similar issue - where I do not wanted to round the value but trim upto 2 decimals
I got the perfect solution for by writing this function and using where ever needed to trim upto 2 decimals
function upto2Decimal(num) {
if (num > 0)
return Math.floor(num * 100) / 100;
else
return Math.ceil(num * 100) / 100;
}
if you call
upto2Decimal(2.3699) or upto2Decimal(-2.3699)
// returns 2.36 or -2.36
check this solution using your JS console of the browser
You can use :
function myFunction()
{
var num = "-54.987656";
var roundedValue = roundMethod(num,5);
document.getElementById("demo").innerHTML = roundedValue;
}
function roundMethod(numberVal, roundLimit) // This method will not add any additional 0, if decimal places are less than the round limit
{
var isDecimal = numberVal.indexOf(".") != -1;
if(isDecimal)
{
if(numberVal.split(".")[1].length > roundLimit)
{
return parseFloat(numberVal).toFixed(roundLimit).toString();
}else
{
return numberVal;
}
}else
{
return numberVal;
}
}
<html>
<body>
<p>Click the button to display the fixed number.</p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
</body>
</html>

Categories