Кол-во точек в круге

185
09 октября 2018, 11:00

На вход принимается радиус(целое число). Нужно вычислить сколько точек входит в круг. Пример:

В данном случае радиус равен 2. В круг с таким радиусом входит 13 точек

Answer 1

Формула окружности известна: x*x + y*y = r.

Соответственно, если расстояние от точки до центра окружности равно радиусу или меньше, то данная точка лежит в круге:

Псевдокод (по умолчанию центр окружности лежит в 0,0. Если нет, то нужно это отдельно учесть):

bool checkInCircle(x, y, r){
    if (math.sqrt(x**2 + y**2) <= r ){
        return True;
        }
    }

Или, допустим, что точка - отдельный класс:

bool checkInCircle(point pt, int r){
    if (math.sqrt(pt.x**2 + pt.y**2) <= r ){
        return True;
        }
    }
Answer 2

Как я понимаю, точки - строго с целочисленными координатами. Если так, то тупо (даю схему)

count = 0
for i = -r to r
    count = count + sqrt(r*r-i*i) * 2 + 1
next i

Под sqrt имеется в виду целочисленное извлечение квадратного корня, с округлением вниз.

Само собой, всё это оптимизируется (можно считать только от 0 до r), но это уже мелочи.

Answer 3

Это задача Гаусса о количестве целочисленных точек в круге радиусом R с центром в начале координат. Явная формула неизвестна, только через сумму ряда

N(r) = 1 + 4 * Floor(r) + 4 * Sum({i=1..Floor(r)}:[Floor(Sqrt(r^2-i^2))])

Edit: по сути, Akina считает тем же методом

Answer 4

Разумный баланс между эффективностью и компактностью буквального алгоритма - это подход из ответа @Akina. Разумеется, имеет смысл использовать такой подход для подсчета точек только в половине круга, а далее аккуратно умножить результат на 2. (Аккуратно - значит помня о том, чтобы не посчитать пограничные точки дважды).

Однако и в буквальном алгоритме можно обойтись без тяжелых/нецелочисленных операций вроде вычисления квадратного корня, если генерировать ограничивающую окружность алгоритмом типа Брезенхэма-Мичнера.

Например, вот такое решение (сорри, на С) пользуется алгоритмом Мичнера для подсчета точек в одной четвертинке и последующего аккуратного (см. выше) умножения результата на 4. При этом для подсчета точек в четвертинке достаточно генерации лишь одной осьмушки дуги окружности (количество итераций цикла в коде ниже соответствует одной осьмушке окружности)

unsigned MichenerCircleCounter(int radius)
{
  int radius2 = radius * radius;
  int x = radius, y = 0;
  int d = 1 - radius;
  unsigned count = 0;
  while (x >= y)
  {
    bool is_inside = x * x + y * y <= radius2;
    unsigned add = (x - y + is_inside) * 2;
    if (add > 0)
      count += add - 1;
    d += d <= 0 ? 2 * ++y + 1 : 2 * (++y - --x) + 1;
  }
  return (count - radius - 1) * 4 + 1;
}

Также по ссылке https://oeis.org/A057655 можно увидеть менее "буквальное" решение Гаусса

A(n) = 1 + 4 * ([n/1] - [n/3] + [n/5] - [n/7] + ...)

где n - это квадрат радиуса круга

unsigned GaussCircleCounter(unsigned radius)
{
  radius *= radius;
  unsigned count = 0;
  for (unsigned divisor = 1; divisor <= radius; divisor += 4)
  {
    count += radius / divisor;
    count -= radius / (divisor + 2);
  }
  return count * 4 + 1;
}
READ ALSO
Как проверить строку на наличие символа "? [закрыт]

Как проверить строку на наличие символа "? [закрыт]

Как проверить строку на наличие символа " ?

179
Кликабельная картинка в приложении android

Кликабельная картинка в приложении android

Всем приветЕсть 4 картинки с разными схемами автомобиля как во вложении

195
Как работать с переменными в разных окружениях?

Как работать с переменными в разных окружениях?

Проблема - несколько окружений, надо протестировать функционал, для прогона теста требуется userIdПользователь один и тот же, но на тесте у него...

158
Shared Preferences не работает

Shared Preferences не работает

Shared Preferences не работает

240