Как определить к какому числу в массиве ближе всего данное число

programmer_2006

Новичок
Как определить к какому числу в массиве ближе всего данное число

Есть число например 16 и массив чисел, например (10, 20, 30) надо определить к какому числу из массива ближе всего данное число. Как это лучше всего сделать? Заранее благодарен.

-~{}~ 24.07.09 13:35:

В математике не селен. Ед. Вариант который придумал это

10 - 16 = -6
20 - 16 = 4
30 - 16 = 14

Получаем массив (-6, 4, 14) из него получаем мин. значения и так определяем к какому числу ближе. Но не знаю насколько такой вариант нормальный и красивый.
 

alexblade

Новичок
хм.. мне тоже интересно.

есть у меня вариант формулами, скорее всего не самый лучший.. но посмотрим что профи скажут
 

programmer_2006

Новичок
Автор оригинала: alexblade
хм.. мне тоже интересно.

есть у меня вариант формулами, скорее всего не самый лучший.. но посмотрим что профи скажут
выложи свой вариант глянуть охото
 

findnext

Новичок
programmer_2006
делай цикл, определяй 2 близлежащих числа. Далее не составит труда сделать вычисления.
 

programmer_2006

Новичок
Мой вариант не корректный написал такой вариант:

PHP:
    $el = 16;
    $array = array(10, 20, 30);
    $result = array();
    $count = count($array);
    
    for ($i = 0; $i < $count; $i++) {
    	if ($el > $array[$i]) {
    		$result[] = $el - $array[$i];
    	}else {
    		$result[] = $array[$i] - $el;
    	}
    }
    
    $min = $result[0];
    $count = count($result);
    for ($i = 0; $i < $count; $i++) {
    	if ($result[$i] < $min) {
    		$min = $result[$i];
    	}
    }
    echo $min;
-~{}~ 24.07.09 13:53:

Автор оригинала: findnext
programmer_2006
делай цикл, определяй 2 близлежащих числа. Далее не составит труда сделать вычисления.
Подробнее плиз. И прокомментируйте мой последний вариант. Ответ получаю подходящий для решения задачи.

-~{}~ 24.07.09 13:58:

Это мне надо для определения результатов опроса, посоветовали просто проверять интервал.
Определение результата по тому к какому числу ближе данное, считаю не корректным
 

DiMA

php.spb.ru
Команда форума
не знаю... но можно померяться, у кого короче =)
 

dimagolov

Новичок
PHP:
if (is_array($array)) {
  $min_idx= -1;
  $min_dif= -1;
  foreach ($array as $idx => $val)
    if ($min_dif < 0 || $min_dif > abs($val - $el)) {
      $min_idx= $idx;
      $min_dif= abs($val - $el);
    }
}
 

DiMA

php.spb.ru
Команда форума
ага... а я то хотел найти сразу 2 ближайших числа (большее и меньшее заданного)
 

dimagolov

Новичок
Нет, не лишнее, у меня там ошибка была ($min_dif < abs($val - $el)). Мы же самое меньшее ищем. Если заранее знать что существует в массиве хоть один ключ и его значение, то да, было бы лишнее, так как начальную разницу можно было бы задать для этого ключа, а так надо или макс. возможную разницу придумывать, или это $min_dif < 0.

п.с. кстати, есть нюанс, что результат abs должен быть unsigned (или иметь размер вдвое больший чем аргументы) тогда когда сами элементы могут иметь знак. для целочисленной арифметики это прокатит (если бы была жесткая типизация), а вот с плавающей точкой потребуется большая разрядность для abs.
 

The employer

Новичок
Автор оригинала: dimagolov
PHP:
if (is_array($array)) {
  $min_idx= -1;
  $min_dif= -1;
  foreach ($array as $idx => $val)
    if ($min_dif < 0 || $min_dif > abs($val - $el)) {
      $min_idx= $idx;
      $min_dif= abs($val - $el);
    }
}
Вместо foreach:
PHP:
usort( $array, create_function( '$a,$b', "return abs(\$a - $val) - abs(\$b - $val);" ) );
echo array_shift( $array );
;)

Чем лично мне действительно нравится PHP - так это своими массивами.
 

dimagolov

Новичок
The employer, а ты подумал как соотносятся затраты памяти и кол-во вычислений в этом случае и в моем? синтаксический сахар вообще очень вреден для здоровья
 

The employer

Новичок
Автор оригинала: dimagolov
The employer, а ты подумал как соотносятся затраты памяти и кол-во вычислений в этом случае и в моем? синтаксический сахар вообще очень вреден для здоровья
В данном конкретном примере - очень плохо соотносятся, согласен. Но если стоит задача именно что-то сделать со всем массивом (например, отсортировать по расстоянию до определенной точки, а не просто найти ближайшую) - то знать про этот сахарок будет полезно.
 

dimagolov

Новичок
кормя кого-то сахаром надо указывать на его вредность. причем чем меньше опыта у пациента, тем более разрушительное действие на его психику оказывает сахар. очевидным примером можно привести пользователей JS-фреймворков, которые не знают синтаксиса самого JS, что, правда, им не мешает писать Web 2.0 приложения, обязательно с либами на десятки килобайт на любой чих.
 

zerkms

TDD infected
Команда форума
dimagolov
в твой вариант добавить бы ещё сортировку и break;
 

dimagolov

Новичок
zerkms, так у меня для массива из N элементов N операций, меньше то никак не сделаешь, не проверив каждый элемент мы ничего о нем сказать не можем. Любая сортировка будет дольше.
 

DiMA

php.spb.ru
Команда форума
> так у меня для массива из N элементов N операций, меньше то никак не сделаешь

В общем случае цикл будет работать всего N/2 раз. И все благодаря сортировке.

PHP:
$x=array(2,7,10,6,2,2,3,6,4,20,20,20,30);
$y=24;

$x[]=$y;
sort($x);

for ($i=0, $return=$x[0]; $i<count($x)-1; $i++) {
    if ($x[$i+1]==$y) {
        if ($i+1>=count($x) || $y-$x[$i] < $x[$i+2]-$y) $return=$x[$i];
        else $return=$x[$i+2];
        break;
    }
    
}

echo $return;
А еще можно полностью ЛИНЕЙНО решить задачу

PHP:
$x=array(2,7,10,6,2,2,3,6,4,20,20,20,30);
$y=24;

if (in_array($y, $x)) {
    $return=$y;
} else {
    $x[]=$y;
    $x=array_unique($x);
    sort($x);
    $x=array_combine($x, $x);
    $keys=array_values($x);
    $key=array_search($y, $keys);
    if ($key+1==count($x)) $return=$x[$keys[$key-1]];
    elseif ($key==0) $return=$x[$keys[$key+1]];
    elseif ($y-$x[$keys[$key-1]] < $x[$keys[$key+1]]-$y) $return=$x[$keys[$key-1]];
    else $return=$x[$keys[$key+1]];
}

echo $return;
Так что забываем про N ;-)
 
Сверху