Обсуждение одной неработающей программы

Program1.pas(30) : Ошибка времени выполнения: Произошла одна или несколько ошибок.

uses graphabc,abcobjects; 
type pix=record
  col:color;
  c:integer;
  end;
var f:file;
p:picture;
r,gps:RectangleABC;
list:linkedlist<pix>;
n:linkedlistnode<pix>;
flag:boolean;
b:pix;
procedure move(x,y,b:integer);
  BEGIN
  r.Text:=getpixel(x,y).A+','+getpixel(x,y).r+','+getpixel(x,y).g+','+getpixel(x,y).b;
  gps.Text:='x='+x+','+'y='+y;
  end;
begin
maximizewindow;
b.c:=1;
list:=new linkedlist<pix>;
p:=picture.create('DSC02337.JPG');
p.Height:=200;
p.Width:=600;
p.Draw(1,1);
r:=RectangleABC.create(1,p.Height+1,100,20,clwhite);
gps:=RectangleABC.create(101,p.Height+1,100,20,clwhite);
for var i:integer:=1 to p.Height-1 do
  {$omp parallel for}
  for var j:integer:=1 to p.Width-1 do
    begin
    n:=list.First;
    flag:=true;
    while (n<>nil) and flag do
      if n.Value.col<>getpixel(j,i) then n:=n.Next
      else
        begin
        inc(n.Value.c);
        flag:=false;
        end;
    if n=nil then begin b.col:=getpixel(j,i); list.AddLast(b) end;
    end;
OnMouseMove:=move;
end.

Если закоментирован последний условный оператор, то ошибка не возникает

А что за ошибка? И работает ли без директивы omp? А то может конфликты в LinkedList?

Ошибка на элементарном - сравнение в цикле:

Program Lab2;
Const 
  b=-2; x0=-0.73; xk=-1.73; h=-0.1; //описание постоянных параметров
label
work; //задание метки
Var 
  y, x: real;  //описание переменных параметров
Begin
  x:=x0;
  work:
    y:=sqrt(abs(x-b))/sqrt(exp(ln(abs(b*b*b-x*x*x))*3))+ln(abs(x-b));//расчёт
    writeln ('x=', x, 'y=', y); //вывод результата на экран
    x:=x+h;
    if x >= xk then //заключаем в модуль, чтобы цикл не зависил от знака переменных
      goto work;
End.

должно вывести 11 строк, а выводит 10. Для проверки x0 поставьте -1,63, он уже выведет 2 строки как надо. В общем не идёт на цикл, когда x у нас равно -1,73.

Спасибо за сове, дело было в директиве, до этого у меня был, другой алгоритм, подходящий для неё, потом я его изменил, а про директиву забыл. Но хотелось бы её применить, а то даже, когда картинка 200*200 долго работает.

Тут не язык виноват, просто не очень хорошо сравнивать на равенство вещественные числа. Мне кажется, программа будет лучше выглядеть так.

    program Lab2;
    
    const b = -2; x0 = -0.73; xk = -1.73; h = -0.1; //описание постоянных параметров

    function f(x : real) : real;
    begin
         Result:= sqrt(abs(x-b))/sqrt(exp(ln(abs(b*b*b-x*x*x))*3))+ln(abs(x-b));
    end;

    begin
         var x := x0;
         while x > xk do
         begin
              writeln ('x = ', x, ' y = ', f(x)); //вывод результата на экран
              x+= h;
         end;
         writeln ('x = ', x, ' y = ', f(xk));
    end.

Спасибо, люблю красивый код, ток лаба не моя и в задании нужно использовать оператор if и метку. Хотя заметьте, в вашей программе тоже идёт сравнение, а исполняется она верно.

У меня сравнение на больше, а не больше-равно. Проверки на равенство не происходит.

А, понял всю соль, спасибо.

Хмм, а вот так тоже не работает.

Program Lab2;
Const 
  b=-2; x0=-0.73; xk=-1.73; h=-0.1; //описание постоянных параметров
label
work; //задание метки
Var 
  y, x: real;  //описание переменных параметров
Begin
  x:=x0;
  work:
    y:=sqrt(abs(x-b))/sqrt(exp(ln(abs(b*b*b-x*x*x))*3))+ln(abs(x-b));//расчёт
    writeln ('x=', x, 'y=', y); //вывод результата на экран
    x:=x+h;
    if not (x < xk) then //сравниваем
      goto work;
End.


Program Lab2;
Const 
  b=-2; x0=-0.73; xk=-1.73; h=-0.1; //описание постоянных параметров
label
start, stop; //задание метки
Var 
  y, x: real;  //описание переменных параметров
Begin
  x:=x0;
  start:
    y:=sqrt(abs(x-b))/sqrt(exp(ln(abs(b*b*b-x*x*x))*3))+ln(abs(x-b));//расчёт
    writeln ('x=', x, 'y=', y); //вывод результата на экран
    x:=x+h;
    if x < xk then // сравниваем
      goto stop
    else
      goto start;
  stop:
End.

Перенес в новую тему

Доьрый вечер. Думаю, что обсуждение касается всё таки ошибок PascalABC, поскольку копмилятор не отрабатывает программу полностью.

Нет. Вы неправильно используете средства распараллеливания. Для графики их использовать нельзя

Прекратите ругать компилятор. Тут проблема в другом. Заведите константу, отвечающую за погрешность, у меня это $eps = 10^{-15}$.

Program Lab2;
Const 
  b=-2; x0=-0.73; xk=-1.73; h=-0.1; eps = 1E-15; //описание постоянных параметров
label
start, stop; //задание метки
Var 
  y, x: real;  //описание переменных параметров
Begin
  x:=x0;
  start:
    y:=sqrt(abs(x-b))/sqrt(exp(ln(abs(b*b*b-x*x*x))*3))+ln(abs(x-b));//расчёт
    writeln ('x=', x, 'y=', y); //вывод результата на экран
    x:=x+h;
    if xk - x > eps then // сравниваем
      goto stop
    else
      goto start;
  stop:
End.

А что мне делать? Это явный показатель его кривой работы, если мне приходится вставлять костыли в элементарную функцию. Это сейчас мы видим где косяк, а если большой проект, мне чтоли каждый цикл вручную считать? Где эта погрешность будет и с каким знаком? Вместо того чтобы спорить, лучше разобраться в чём косяк. Если вы разработчик, то имейте смелость признать кривую работу компилятора.

Я имел возможность написать, что компилятор криво работает и, ничего не делая, превратиться в разработчика PascalABC.NET. Но не буду, ибо я не разработчик и компилятор работает хорошо. В вашей задаче могут произойти неточности в хранении вещественных чисел, они у вас и произошли. Если вы мне не верите, запустите ваш чудесный код (например, самый первый) в Lazarus, и вы убедитесь, что не правы, ну или можете пожурить их за “кривую работу компилятора”.

Видимо, курс архитектуры компьютера прошёл для вас зря :frowning:

Такова работа с вещественными числами на большинстве современных процессоров общего назначения (стандарт IEEE 754).

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

1 лайк

Спасибо, не знал, что проблема может быть в самом фундаментальном.