Question

Not sure if that is the right way to ask this or not but here is the problem.

Given a latitude of 26.746346081599476, how do I find the number 26.75 as the 16th greater than the number and 26.6875 as the 16th lower than the number?

26.0
26.0625
26.125
26.1875
26.25
26.3125
26.375
26.4375
26.5
26.5625
26.625
26.6875
My Number: 26.746346081599476
26.75
26.8125
26.875
26.9375
27.0

I'm using JavaScript so an answer in that would be helpful but not necessary. I could brute force it but I'm looking for the elegant way to do it.

The bigger picture is that I want to create standard tiles for a mapping application I'm working on. We are using Bing maps and I am loading data on-demand, every time the user pans or zooms in. It would be nice to take advantage of server side caching for these requests so if I standardize the queries sent to the server I would get some cache hits. If I don't standardize the requests to the server it is highly unlikely that the same user would be viewing the exact some location at the same time.

So there is a higher chance of getting cache hits with: /path/data.json?tl=26.6875,-80.6875&br=26.75,-80.75 than with: /path/data.json?tl=26.74946187679896,-80.10930061340332&br=26.743234270702878,-80.09607195854187

Any outside the box answers are welcome as well.

Was it helpful?

Solution

To find the nearest multiples of 1/n:

lower_bound = 1.0 / n * Math.floor(n * your_number);
upper_bound = 1.0 / n * Math.ceil(n * your_number);

You may want to use some special handling if your number is already a multiple of 1/16.

// alternate solution so that lower_bound <= your_number < upper_bound
lower_bound = 1.0 / n * Math.floor(n * your_number);
upper_bound = 1.0 / n * Math.floor(n * your_number + 1.0);

OTHER TIPS

You multiply the value by 16, use the floor or ceil method, and divide by 16:

var higher = Math.ceil(number * 16) / 16;
var lower = Math.floor(number * 16) / 16;
function bounds(number, numerator, denominator) {
  var frac = denominator/numerator;
  return {
    lower: Math.floor(frac * number) / frac,
    upper: Math.ceil(frac * number) / frac,
  }
} 


bounds(26.746346081599476,1,16)
// returns an object with properties
// lower : 26.6875 
// upper : 26.75

Sounds like rounding to the nearest 16th…

rounded = Math.round(number * 16) / 16;

You could get numbers that aren't exact because of the float representation, but that shouldn't matter in your case if you use it just for caching.

What is the smallest fractions you are interested in splitting? IE are 16ths going to be the smallest increments?

If yes, simply multiply your number by 16. Trunc it to an int and divide by 16 to find the lower bound. Trunc it to an int, add 1, then divide by 16 to find the upper bound.

A couple of strategies not posted so far:

A) create a lookup table that maps the digits after the decimal to the nearest 16th. Just use whatever precision you need (probably hundredths).

B) create a table of all the 16ths from 0 to 1, and do a binary style search with your number % 1.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top