I have this progress bar in JS and I'm filling up progress by increasing its width using this code:
function move(ValueSC) {
var elem = document.getElementById("scaleOrig");
var width = 0;
var internalVlue = ValueSC;
var id = setInterval(frame(internalVlue), 50);
function frame(internalVlue) {
if (width >= internalVlue) {
clearInterval(id);
} else {
width += internalVlue;
elem.style.width = width + '%';
}
}
}
This works perfectly but the problem is that I will get a value (result) from my calculator which is something between numbers 15 to 40, so with this stated 15 will be 0% and 40 will 100%. I want the width of progress bar to go up to 100 percent if the result (from my calculator) is 40 and if it is 15 the value of progress bar should be 0%. Basically I need the logic to convert all the 25 numbers from 15 to 40 to have a percentage value between 0 to 100%.
As a broader answer, the formula you're looking for is ((value - min) / (max - min)) * 100. max and min are the bounds of your value and value is the current progress. This will return the percentage of the progress so far for any given value between two other values.
var percent = ((value - 15) / (40 - 15)) * 100
40 will give you 100 and 15 will give you 0
Before you call your method do this:
ValueSC= ((Max-Min)/100)*(Current-Min))
Where:
Current: Your value
Min = Minimum Value
Max = Max Value
First you have to divide up 100 to smaller steps. There can be 25 (40-15) different values for your number, so the length of a step should be 100 / 25, and your starting number is 15. Something like this should work:
function getPercentage(number) {
return (number - 15) * (100 / 25);
}
I have a logarithmic scale going from 0 to 100:
0.00
0.10
1.00
10.00
100.00
I need to make a pie chart which has 4 quarters.
the first is going from 0 to 0.10
the second is from 0.10 to 1 etc.etc.
So if I have the value 25, it should be calculated which percentage this is in the logarithmic scale. Considering the scale it should end up somewhere in the last quarter of the chart.
Unfortunately my understanding of Maths does not reach this far ;)
Could you help out and tell me where to start.
I thought of looking at each quarter as a 100% piece, and then calculate where this might be in this quarter..
per example:
32 > 10 so it should be in the last quarter (percentage wise above 75%)
So in this last quarter 32 will be in:
((32-10) x 100) / (100 - 10) = 24.44% in this quarter
Making this 24.44 / 4 = 6.11% over 4 quarters and thus 75 + 6.11 = 81.11% of the whole chart.
Now this would work, but I am looking for a shorter and simpler way of calculating this.
Can you please help out.
This is surely a maths question about plotting values on a logarithmic
scale, and not really anything to do with JavaScript in particular or
programming in general. Anyhow ...
You need to decide on a minimum value, since the logarithm of zero is
undefined. Once you have your maximum and minimum logarithms, you can
scale your values as you wish. Slightly ontopic: JavaScript has
Math.log10 in more up-to-date engines (and can be readily
defined if not, e.g. as in #NinaScholz's answer or using the polyfill here).
var minval = 0.01,
maxval = 100,
minlog = Math.log10(minval),
maxlog = Math.log10(maxval),
range = maxlog - minlog,
lineartolog = function(n){
return (Math.log10(n) - minlog) / range;
},
logplots = [
0.01,
0.1,
1,
3.2,
10,
32,
75,
100
].map(lineartolog);
document.body.innerHTML = '<pre>' + logplots + '</pre>';
Adjust as required for percentages, radians, etc.
Consideration:
q0 q1 q2 q3
01234567890123456789012345678901234567890
| | | | |
0.01 0.1 1 10 100
0.32 3.2 32
because log10(32) = 1.505 = 1 + 0.505
because log10(3.2) = 0.505 = 0 + 0.505
because log10(0.32) = -0,495 = -1 + 0.505
^ ^
quadrant after adding 2 amount to fill
together, fill is the amount in %:
function log10(f) {
return Math.log(f) / Math.log(10);
}
function getValue(v) {
var l = log10(v),
quadrant = Math.floor(l) + 2,
fill = (l - Math.floor(l)) * 100;
return { quadrant: quadrant, fill: fill };
}
console.log('0.32', getValue(0.32));
console.log('3.2', getValue(3.2));
console.log('32', getValue(32));
Say you get values anywhere from 0 to 1,000,000,000, and you want to plot 30 days. So one particular chart may have a set like:
[ 1, 465, 123, 9, ... ]
While another chart can have a set with much larger numbers:
[ 761010, 418781, ... ]
Is there an "optimal algorithm" that can take those values and segment them into "clean" numbers? Sorry for the wording, don't know the right terminology, I will try to explain.
By "optimal algorithm", I mean both in terms of minimum number of computational steps, given that it creates labels (say for the y-axis) that are simplest from a human perspective.
For example, say you always want to divide the y-axis into 5 labels. You could do this:
var max = Math.max.apply(Math, values); // 465 (from the first set of values)
var interval = max / 5;
var labels = [ interval * 0, interval * 1, interval * 2, ... ];
But that creates labels like:
[ 0, 93, 186, ... ]
And that would be complex for humans to understand. What would be better (but still not ideal) is to create labels like:
[ 0, 125, 250, 375, 500 ]
But that's still to specific. Somehow it should figure out that a better segmentation is:
[ 0, 200, 400, 600, 800 ]
That way, it's divided into more intuitive chunks.
Is there a standard way to solve this problem? What algorithm works best?
Some maths
var getLabelWidth = function(sep, max_value){
var l = (""+max_value).length;
var av = max_value/sep/Math.pow(10,l-2); // get the length max 2 digit
/// 15.22
var width = (Math.ceil(av)*Math.pow(10,l-2)); // do a ceil on the value retrieved
// and apply it to the width of max_value.
// 16 * 10 000
return width;
}
console.log(getLabelWidth(2,59)); // 30 : [0, 30, 60]
console.log(getLabelWidth(2,100)); // 50 : [0, 50, 100]
console.log(getLabelWidth(2,968)); // 490 : [0, 490, 980]
console.log(getLabelWidth(3,368)); // 130 : [0, 130, 260, 390]
console.log(getLabelWidth(3,859)); // 290 : [0, 290, 580, 870]
console.log(getLabelWidth(3,175)); // 60 : [0, 60, 120, 180]
console.log(getLabelWidth(3,580)); // 200 : [0, 200, 400, 600]
console.log(getLabelWidth(3,74)); // 25 : [0, 25, 50, 75]
console.log(getLabelWidth(4,1111)); // 300 :[0, 300, 600, 900, 1200]
console.log(getLabelWidth(4,761010)); // 200 000: [0, 200000, 400000, 600000, 800000]
It could be improved a little bit i guess,
sorry for my bad english .
For reference, here's what I ended up doing.
function computeLabels(count, max) {
var magnitude = orderOfMagnitude(max);
var multiplier = magnitude * count;
// 1
if (multiplier >= max) return buildLabels(count, multiplier);
// 2
multiplier *= 2;
if (multiplier >= max) return buildLabels(count, multiplier);
// 5
multiplier *= 5;
if (multiplier >= max) return buildLabels(count, multiplier);
// 10, don't think it will ever get here but just in case.
multiplier *= 10;
if (multiplier >= max) return buildLabels(count, multiplier);
}
function buildLabels(count, multiplier) {
var labels = new Array(count);
while (count--) labels[count] = formatLabel(count * multiplier);
return labels;
}
function formatLabel(value) {
if (value > 10e5) return (value / 10e5) + 'M'; // millions
if (value > 10e2) return (value / 10e2) + 'K'; // thousands
return value; // <= hundreds
}
function orderOfMagnitude(val) {
var order = Math.floor(log10(val) + 0.000000001);
return Math.pow(10, order);
}
After drawing it out on paper, the "desirable" labels seemed to follow a simple pattern:
Find the max value in the set.
Get the order of magnitude for it.
Multiply the order of magnitude by the number of ticks.
Iterate: If that previous calculation is greater than the max value, then use it. Otherwise, multiply the value times 2 and check. If not, try times 5. So the pattern is, 1, 2, 5.
This gives you labels that are like:
10, 20 (2 ticks)
20, 40
50, 100
100, 200
200, 400
500, 1000
...
10, 20, 30 (3 ticks)
20, 40, 60
50, 100, 150 (don't like this one too much but oh well)
100, 200, 300
10, 20, 30, 40 (4 ticks)
...
It seems like it can be improved, both in producing better quality "human readable" labels, and in using more optimized functionality, but don't quite see it yet. This works for now.
Would love to know if you find a better way!
How do you round down a number before the decimal points
So not 45.1 -> 45
But 47 -> 45
Or 45 -> 50
Try like this:-
Math.round(45/ 10) * 10;
var number = 45.5;
alert(Math.round(number / 5) * 5);
This rounds to nearest 5.
var number = 45.5;
alert(Math.round(number / 10) * 10);
And this to nearest 10.
There is also a function floor that rounds to lower number and ceil that rounds to higher number` for example:
var number = 45.5;
alert(Math.floor(number / 10) * 10); // This will give 40
alert(Math.ceil(number / 10) * 10); // This will give 50
I have a number variable that is between 0 and 100. It ccould be something like 83.333334.
I want to use Math.Round to round the number (e.g. Math.round(83.333334);). How can I do this so that the result is always divisible by five (i.e. in the set [0, 5, 10, 15... 85, 90, 95, 100])?
Divide by 5, round it, multiply by 5.
alert(Math.round(83 / 5) * 5);
jsFiddle Demo
function roundDownToMultiple(number, multiple) {
return number - (number % multiple);
}
roundDownToMultiple(86, 5); // 85
roundDownToMultiple(89, 5); // 85
roundDownToMultiple(96, 5); // 95
Use the modulus operator to "round" down your number to a multiple of 5, see the example below.
var x = Math.round(83.333334);
x = x - (x % 5);
If you'd like to "round towards zero" (and have a correct value for negative numbers aswell) use something like this:
x = Math[x < 0 ? 'ceil' : 'floor'] (x/5) * 5;
Using this Math.round(Math.floor(Math.random() * 100) / 5) * 5 You can get the Numbers divisible by 5.
100 - is the range of the Result.
Give this a try.
Math.round(val / 5) * 5;