Formula for returning a bin of 10th or 100th
I need a function that should give me a 10th or 100th array, for example
- If i pass 5, it should return 1 to 10
- If i pass 67, it should return 1 to 100
- If i pass 126, it should return 101 to 200开发者_StackOverflow社区
- If i pass 2524, it should return 2001 to 3000
Any guidance?
Other people are giving you good answers, but I'm not sure they're highlighting the important principle, which is:
You're looking for a function that depends on the "order of magnitude" of a given number. Logarithms are probably the easiest way of getting that information.
A log base 10 more or less answers the question "What's the largest power of 10 this number is divisible by?" or "How many times could I divide this number by 10 before it would be less than one?"
You could write a function which answers this question manually, of course:
function divsBy10(n) {
var i = 0;
while(n > 1) {
n = n/10;
i++;
}
return i-1;
}
And the overhead wouldn't be high. I'd guess it's a bit faster to use natively implemented math functions, though. Of course, it doesn't look like you get a native log base 10 in Actionscript... it appears Math.log is a natural log (log base e). There's a mathematical identity which says log_10 x = log_e x / log_e 10 ... and ActionScript does give you a log_e 10 as a constant (Math.LN10). So,
function log10(n) {
return Math.log(n)/Math.LN10;
}
Now, log10 won't yield an integer answer to the questions I mentioned above ("How many times could I divide n by 10 before it's less than 1?"), because it's actually the inverse of 10^n, but the integral portion of the return value will be the answer to that question. So you'd want to do Math.floor on the value you get back from it, and from there, do the various computations you'll need in order to get the specific array ranges you need.
This gives you what you asked for:
function FunkyRange (TargNum)
{
var OrderOfMag = Math.floor (Math.log (TargNum-1) / Math.LN10);
var NaturalLimLow = Math.pow (10, OrderOfMag);
var AdjustedLimLow = Math.floor ((TargNum-1) / NaturalLimLow) * NaturalLimLow + 1;
var AdjustedLimHigh = NaturalLimLow + AdjustedLimLow - 1;
//-- Handle special cases For TargNum <= 10 and <= 100.
if (AdjustedLimLow <= 100)
AdjustedLimLow = 1;
if (AdjustedLimHigh <= 10)
{
AdjustedLimHigh = 10;
}
else
{
if (AdjustedLimHigh < 100)
AdjustedLimHigh = 100;
}
return [AdjustedLimLow, AdjustedLimHigh];
}
Which returns:
Input Lim, Low Lim, High
----- ---------- -----------
5 1 10
67 1 100
99 1 100
100 1 100
126 101 200
200 101 200
299 201 300
473 401 500
2524 2001 3000
As commenters have mentioned, your ranges aren't entirely consistent. Here's my interpretation where 67 yields 61-70:
function range(n) {
var digits = Math.ceil(Math.log(n) / Math.LN10);
var spread = Math.max(Math.pow(10, digits - 1), 10);
var low = Math.floor((n - 1) / spread) * spread;
var high = low + spread;
return [low + 1, high];
}
Results, including some edge cases:
5: [1, 10]
67: [61, 70]
126: [101, 200]
2524: [2001, 3000]
100: [91, 100]
1000: [901, 1000]
999: [901, 1000]
p = floor(log10(N))
range = 10^p
base = floor(N/range) * range
for example
log10(258) => 2.4
floor(2.4) => 2
range := 10^2 => 100
base := floor(258/100)*100 => 200
(except this assumes that for 67, you really want 60..70)
精彩评论