Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Паскаль, Turbo Pascal, PascalABC.NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.09.2011, 15:53   #21
JuniorProger
Форумчанин
 
Регистрация: 16.09.2011
Сообщений: 114
По умолчанию

Цитата:
Сообщение от evg_m Посмотреть сообщение
Нет, все целые точки лежат на лучах с углами в целые градусы (0-360). а могут и не лежать
Согласен.
Посмотри пост #10. Stilet говорит, что счетчик цикла показывает количество точек с целыми координатами внутри окружности (ну как в задании).
JuniorProger вне форума Ответить с цитированием
Старый 27.09.2011, 20:25   #22
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

пост #6 от JuniorProger
совсем немного не дотянул до хорошего решения.
Цитата:
Код:
n:=0;
for y:=trunc(y0-r) to trunc(y0+r) do begin
  left_border:=trunc(x0-sqrt(sqr(r)-sqr(y-y0)));
  right_border:=trunc(x0+sqrt(sqr(r)-sqr(y-y0)));
  for x:=left_border to right_border do
    inc(n);
end;
смотрим последние две строчки
внутри цикла чисто +1 какое-то число раз.
заменяем цикл на
Код:
n:=n+(right,border -left.border);
получаем

Код:
for y:=trunc(y0-r) to trunc(y0+r) do 
  n:=n+(trunc(x0+sqrt(sqr(r)-sqr(y-y0))) -trunc(x0-sqrt(sqr(r)-sqr(y-y0))));
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 27.09.2011 в 20:32.
evg_m вне форума Ответить с цитированием
Старый 27.09.2011, 22:00   #23
JuniorProger
Форумчанин
 
Регистрация: 16.09.2011
Сообщений: 114
По умолчанию

Цитата:
Сообщение от evg_m Посмотреть сообщение
пост #6 от JuniorProger
совсем немного не дотянул до хорошего решения.

смотрим последние две строчки
внутри цикла чисто +1 какое-то число раз.
заменяем цикл на
Код:
n:=n+(right,border -left.border);
получаем

Код:
for y:=trunc(y0-r) to trunc(y0+r) do 
  n:=n+(trunc(x0+sqrt(sqr(r)-sqr(y-y0))) -trunc(x0-sqrt(sqr(r)-sqr(y-y0))));
Нужно прибавлять +1 иначе не будет учтена одна точка для каждого Y! Смотреть пост #6 нижнее решение
JuniorProger вне форума Ответить с цитированием
Старый 27.09.2011, 22:43   #24
TinMan
Форумчанин
 
Аватар для TinMan
 
Регистрация: 05.09.2011
Сообщений: 869
По умолчанию

Цитата:
Сообщение от JuniorProger Посмотреть сообщение
Функция trunc не зависит от знака! Сам проверял: она берет целую часть от модуля числа, потом добавляет знак, если был таковой. Поэтому не важно, какое число (положительное или отрицательное), trunc всегда возьмет только целую часть!
JuniorProger, просто подумай над тем, что ты сказал.
И еще раз прочти мой пост выше.
Уверен, ты поймешь ).
Предпочитаю на "ты".
TinMan вне форума Ответить с цитированием
Старый 28.09.2011, 01:30   #25
JuniorProger
Форумчанин
 
Регистрация: 16.09.2011
Сообщений: 114
По умолчанию

Цитата:
Сообщение от TinMan Посмотреть сообщение
JuniorProger, просто подумай над тем, что ты сказал.
И еще раз прочти мой пост выше.
Уверен, ты поймешь ).
Я понял, что при отрицательном входном значении trunc вернет число большее либо равное входному (но меньшее или равное по модулю), а при положительном - меньшее или равное.
Под знакозависимой я (да и не только) понимаю функцию, результат работы которой зависит от знака аргумента. Но Trunc при любом входном значении (отрицательном или положительном) вернет целую часть. Вот, скажем, sqrt() - знакозависимая, т.к. при положительном аргументе она вернет корень, а при отрицательном - ошибку.

Ну да ладно, каждый пусть думает как хочет
JuniorProger вне форума Ответить с цитированием
Старый 28.09.2011, 02:12   #26
TinMan
Форумчанин
 
Аватар для TinMan
 
Регистрация: 05.09.2011
Сообщений: 869
По умолчанию

Цитата:
Сообщение от JuniorProger Посмотреть сообщение
Ну да ладно, каждый пусть думает как хочет
Не в этом дело. Дело в правильности результата программы. Я отметил, что если использовать trunc, то нужны поправки на знак. Если ты настроен спорить о терминах, то рассмотри график функции trunc и заметь, что при смене знака аргумента ход графика претерпевает некий "излом". Но на самом деле строгого термина такого нет, и все, что я хотел сказать этим словом - что нужно учитывать знак аргумента.

Выше я уже сказал, как с этим бороться. Могу повторить то же самое на Pascal.
Код:
  // сначала сдвигаем круг (если нужно) так, чтобы он был полностью в первом квадранте:
  d:= x0 - r;
  if d<0 then x0:= x0 + Trunc(-d) + 2;
  d:= y0 - r;
  if d<0 then y0:= y0 + Trunc(-d) + 2;
  // теперь можно считать точки с использованием trunc, не волнуясь о знаках
  // ...
Но есть лучшее решение этого вопроса. Более красивое, более общее, более простое и ясное, не перегруженное проверками. Не знаю, стоит ли приводить его после того, как задача решена..
Предпочитаю на "ты".

Последний раз редактировалось TinMan; 28.09.2011 в 02:18.
TinMan вне форума Ответить с цитированием
Старый 28.09.2011, 11:04   #27
puporev
Старожил
 
Регистрация: 13.10.2007
Сообщений: 2,740
По умолчанию

Цитата:
Не знаю, стоит ли приводить его после того, как задача решена.
Конечно стоит, ибо я например не уверен что она решена для r=1000000.
puporev вне форума Ответить с цитированием
Старый 28.09.2011, 14:43   #28
JUDAS
фонатик DELPHI
Форумчанин
 
Аватар для JUDAS
 
Регистрация: 14.01.2008
Сообщений: 714
По умолчанию

Код:
function Ceil(const X: Extended): Integer;
begin
  Result := Integer(Trunc(X));
  if Frac(abs(X)) > 0 then
  case X>0 of
   true : Inc(Result);
   false: Dec(Result);
  end;
end;


function PointCountByCircle(Cx,Cy ,R : double) : integer;
var Rin,Rout : TRect;
    i,j,dx   : integer;
    D,insize : double;
begin
 // 1. ищем вписаный квадрат с окрулением координат углов к центру
 D := R*cos(pi/8);
 Rin.Left:= Trunc(Cx-D);  Rin.Right  := Trunc(Cx+D);
 Rin.Top := Trunc(Cy+D);  Rin.Bottom := Trunc(Cy-D);

 // 2. ищем описаный квадрат с округлением координат сторон от центра
 Rout.Left:= Ceil(Cx-R-1E-8);  Rout.Right  := Ceil(Cx+R+1E-8);
 Rout.Top := Ceil(Cy+R+1E-8);  Rout.Bottom := Ceil(Cy-R-1E-8);
 insize := Rin.Right-Rin.Left;
 result := 1;
 if insize<>0 then result := round(sqr(insize+1));

 for j:= Rout.Bottom to Rout.Top do
 begin
   for i:= Rout.Left to Rin.Left-1 do
   inc(result, byte(sqrt(sqr(i-Cx)+sqr(j-Cy))<=R));
   for i:= Rin.Right+1 to Rout.Right do
   inc(result, byte(sqrt(sqr(i-Cx)+sqr(j-Cy))<=R));
 end;

 if insize=0 then dx:=0 else dx:=1;

 for i:= Rin.Left+dx to Rin.Right-dx do
 begin
   for j:= Rout.Bottom to Rin.Bottom-1 do
   inc(result, byte(sqrt(sqr(i-Cx)+sqr(j-Cy))<=R));
   for j:= Rin.Top+1 to Rout.Top do
   inc(result, byte(sqrt(sqr(i-Cx)+sqr(j-Cy))<=R));
 end;

end;
такой код прокатит?
по крайней мере не "маслает" вписанный в круг квадрат, который и так внутри (проверяется желтая область)

радиус = 100000 считало минуты 2 с результатом - 1348027629 точек
95% сбоев и ошибок приложений, находится в полу метрах от монитора

Последний раз редактировалось JUDAS; 28.09.2011 в 14:50.
JUDAS вне форума Ответить с цитированием
Старый 28.09.2011, 16:35   #29
TinMan
Форумчанин
 
Аватар для TinMan
 
Регистрация: 05.09.2011
Сообщений: 869
По умолчанию

Цитата:
Сообщение от JUDAS Посмотреть сообщение
такой код прокатит?
по крайней мере не "маслает" вписанный в круг квадрат,
Боюсь, этого мало..
Цитата:
радиус = 100000 считало минуты 2 с результатом - 1348027629 точек
Во-первых, ты не сказал координаты центра круга. Во-вторых, результат явно неверный, поскольку приблизительно при r=10^5 он должен быть такой:
S = 3.1415925*10^10

Вот мой код, который для r=10^6 просчитал практически мгновенно (для 10^7 примерно секунду), при этом я даже не отключал отладочный режим. В этом коде вместо функции trunc используются две функции: Up и Down - которые выдают соответственно ближайшее большее и ближайшее меньшее целое. Эти функции очень полезно написать и иметь в своей библиотеке. Думаю, вас не затруднит это сделать..
Код:
uses MyLib;
var
  r,x,y,a: double;
  i: LongInt;
  n: comp;

begin
  readln(r,x,y);
  n:= 0;
  for i:= Up(x-r) to Down(x+r) do begin
    //writeln(x-i);
    a:= Sqrt(r*r-Sqr(x-i));
    n:= n + Down(y+a) - Up(y-a) + 1
  end;
  write(n);
  readln
end.
Результаты для сравнения такие:
Код:
Running "h:\...\circle.exe "
1000000 1.234 5.6789
3141592653367
Running "h:\...\circle.exe "
10000000 1.234 5.6789
314159265358851
Предпочитаю на "ты".
TinMan вне форума Ответить с цитированием
Старый 28.09.2011, 18:19   #30
JUDAS
фонатик DELPHI
Форумчанин
 
Аватар для JUDAS
 
Регистрация: 14.01.2008
Сообщений: 714
По умолчанию

координаты центра круга = 0,0
TinMan, а что собственно твой код считает ?
95% сбоев и ошибок приложений, находится в полу метрах от монитора
JUDAS вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
треугольник и круг zhenya.ya Общие вопросы C/C++ 0 16.05.2011 02:32
Многоугольник и круг Никита_96 Паскаль, Turbo Pascal, PascalABC.NET 2 09.02.2011 21:10
Круг на ассемблере Hesheit Помощь студентам 6 13.05.2009 22:48
Паскаль Круг ! BuTeK1 Паскаль, Turbo Pascal, PascalABC.NET 4 08.01.2009 14:27
точки плоскости, заданные своими координатами, попадают в круг с радиусом R Jondeer Общие вопросы C/C++ 6 16.06.2008 00:06