开发者

Given a degree x, find the nearest degree in an array of degrees

I have an array of degrees, [10, 90, 200, 280, 355] for a circle.开发者_运维技巧

I'm given a degree, let's say 1. How do I determine that 1 is closest to 355 degrees?


Subtract the two numbers. If the difference is larger above 180 [or below -180], subtract [or add] 360. Now you can just compare absolute values of the difference.


Here is an actual formula:

degreediff = min(abs(x-y),360-abs(x-y))


This is more compact and efficient:

function difference(a, b) {
    var d = Math.abs(a - b);
    return d > 180 ? 360 - d : d;
};

function closest(a, bs) {
    var ds = bs.map(function(b) { return difference(a, b); });
    return bs[ds.indexOf(Math.min.apply(null, ds))];
};

> difference(1, 355)
6

> closest(1, [10, 90, 200, 280, 355])
355


You have one value which will contain the closes degree found found_degree and one for the actual difference degree_difference.

Next, iterate over the whole array and calculate two values: abs(degree_at_position - target_degree) and abs(degree_at_position - 360 - target_degree). If one of those values is smaller than degree_difference, you have a closer degree - store it in found_degree and update degree_difference accordingly.

That's it.

You maybe should initialise found_degree with -1 and degree_difference with 360, just to make sure you can properly interpret the result in case of an empty given array as well - or you simply handle the case of an empty input array separately.

Is this a homework, by the way?


The brute force approach would be something like this:

var closestElement;
var closestDivergence = 360;

var toCompare = 355;
var choices = [1, 90, 200, 280, 355];

for(i=0;i<choices.length;i++){
    var currentDivergence=choices[i] - toCompare;
    if (currentDivergence<0) {
        currentDivergence+=360;
    }
    if (currentDivergence < closestDivergence){
        closestDivergence = currentDivergence;
        closestElement = i;
    }
}

if (closestElement != NaN){
    alert('Closest value is '+choices[closestElement]);
}


Here's a nice little quickie

function closest(deg,ar) {
  return ar.sort(function(a,b){var c = deg; return Math.min(360 - (a-c),Math.abs(a-c)) - Math.min(360 - (b-c),Math.abs(b-c))})
}
var myArray = [355, 280, 200, 181, 90, 30];
alert(closest(180,myArray));

Sorts and returns the array according to which one is closest to the provided degree. Index 0 is closest. It does wrap making 355 closer to 0 than 10.


First check the array (check which element is closest) using the given degree (1 in your example), then add 360 and check with that degree (361). Compare which result is better:

x the given degree, y the first result, z the second result

if (abs(x-y) < 360+x-z)
    choose y;
else
    choose z;

If the array is sorted you can check it with a binary sort which gives you O(log n) time in worst case scenario. Otherwise you have to browse through the whole array two times.


This formula will only work with circles. It's pseudo code of course.

 degree diff = min(abs(x-y),360-abs(x-y))


Using the comments from this page I managed to come up with this code:

function closest(deg, degs) {

deg = (deg / 360 > 1 ? deg - (Math.floor(deg / 360)*360) : deg);

var difference = 360;
var closest = -1;

for(i=0;i<degs.length;i++) {

    var x = degs[i];

    var diff = Math.min(Math.abs(x-deg),360-Math.abs(x-deg))

    if(diff <= difference) {
        closest = i;
        difference = diff;
    }
};

return closest;

}

closest(1000, [10, 90, 200, 280, 355]);

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜