Учитывая степень х, найти ближайшую степень в массиве градусов - PullRequest
7 голосов
/ 16 августа 2011

У меня есть массив градусов, [10, 90, 200, 280, 355] для круга.

Мне дали степень, скажем, 1. Как определить, что 1 ближе всего к 355 градусам?

Ответы [ 9 ]

4 голосов
/ 16 августа 2011

Вычтите два числа.Если разница больше 180 [или меньше -180], вычтите [или прибавьте] 360. Теперь вы можете просто сравнить абсолютные значения разности.

3 голосов
/ 16 августа 2011

Вот актуальная формула:

degreediff = min(abs(x-y),360-abs(x-y))
1 голос
/ 06 декабря 2013

Это более компактно и эффективно:

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
0 голосов
/ 26 сентября 2011

Используя комментарии с этой страницы, мне удалось придумать этот код:

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;

}

ближайший (1000, [10, 90, 200, 280, 355]);

0 голосов
/ 17 августа 2011

Эта формула будет работать только с кругами.Это псевдокод, конечно.

 degree diff = min(abs(x-y),360-abs(x-y))
0 голосов
/ 17 августа 2011

Сначала проверьте массив (проверьте, какой элемент является ближайшим), используя заданную степень (1 в вашем примере), затем добавьте 360 и проверьте с этой степенью (361).Сравните, какой результат лучше:

x заданный градус, y первый результат, z второй результат

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

Если массив отсортирован, вы можете проверить его с помощью двоичной сортировки, которая даетВы O (log n) время в худшем случае.В противном случае вам придется просматривать весь массив два раза.

0 голосов
/ 16 августа 2011

Вот хорошая маленькая подсказка

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));

Сортирует и возвращает массив, в соответствии с которым он ближе всего к предоставленной степени.Индекс 0 является ближайшим.Это делает обтекание, делая 355 ближе к 0, чем 10.

0 голосов
/ 16 августа 2011

Подход грубой силы будет выглядеть примерно так:

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]);
}
0 голосов
/ 16 августа 2011

У вас есть одно значение, которое будет содержать найденную степень закрытия found_degree и одно для фактической разницы degree_difference.

Затем выполните итерацию по всему массиву и вычислите два значения: abs(degree_at_position - target_degree) и abs(degree_at_position - 360 - target_degree). Если одно из этих значений меньше degree_difference, у вас есть более близкая степень - сохраните его в found_degree и обновите degree_difference соответственно.

Вот и все.

Возможно, вам следует инициализировать found_degree с -1 и degree_difference с 360, просто чтобы убедиться, что вы можете правильно интерпретировать результат и в случае пустого заданного массива - или вы просто обрабатываете случай пустого ввода массив отдельно.

Кстати, это домашнее задание?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...