22.03.2010, 08:12. Показов 19735. Ответов 3
Дарова Всем)
Столкнулся с теоретически невозможной ошибкой (!=) округления Real-дробного числа
на таком участке кода:
| Pascal | ||
|
где эти переменные объявлены как:
| Pascal | ||
|
Ошибка происходит на участке
| Pascal | ||
|
И описыается справкой как:
Код
>> 201: Ошибка Проверки диапазона >> 201: Range Check Error Являющаяся ошибкой во время выполнения. Появляется в случаях когда 1) Индекс Массива вне диапазона 2) Назначение Переменной значения вне её диапазона 3) Передача Функции значения вне её диапазона
Склоняюсь к третьему варианту. Но не представляю, что нужно сделать Real`у чтобы он вышел за границы
Вступление:
Пишу Игру.
X1,Y1 и X2,Y2 = это реальные координаты объекта в игре
DrwX1,DrwY1 и DrwX2,DrwY2 = это округленные те же координаты, только округленные.
Используются как параметры для отрисовки объекта на экране.
Реальные координаты (X1,Y1 и X2,Y2) раз в 100мс меняются на значение скорости.
Иксы — смещаются на горизонтальную скорость hspeed,
Игреки — на вертикальную скорость vspeed
| Pascal | ||
|
Чтобы Объект на своем пути сталкивался с другими объектами, а не перскакивал сразу через 24 пикселя —
Я ввел код Пошагового Передвижения.
| Pascal | ||
|
После такого перемещения рассчитываются новые координаты(DrwX1,DrwY1 и DrwX2,DrwY2) в которых будет отрисован объект.
Добавлено через 8 минут
———————————————————-
Всё! Есть)))
Нашел ошибку!)))
Кусок Призрак попался)))
Я его вам выделил как красную строку:
| Pascal | ||
|
Всё)) Спасибо Всем Кто ПрочитаЛ)))
Для любознательных привожу Исходник Системы Передвижения))
| Pascal | ||
|
Если будут вопросы -пишите в личку 
Поки)
———————————————————-
Щас еще скольжение Тела вдоль Соседних физических объектов при невозможности переместится на их положение пропишу))
Вообще класс будет =))
А Потом Экзешку выложу)))
Отпразднуем!))) 
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
1
Умея
пользоваться массивами, условными
операторами и операторами цикла, вы
можете писать довольно серьезные
программы. При выполнении этих программ
неизбежно будут возникать критические
ошибки, приводящие к аварийному завершению
программы. Такие ошибки по английски
называются Run-time errors — ошибки времени
выполнения. Рассмотрим пока только
наиболее часто встречающиеся арифметические
ошибки:
Division
by zero — код ошибки 200;
Arithmetic
overflow — код ошибки 215;
Range
check error — код ошибки 201;
Floating
point overflow — код ошибки 205;
Invalid
floating point operation — код ошибки 207.
Ошибка
Division
by zero
— деление на ноль — возникает при выполнении
операций DIV,
MOD
и /,
когда делитель равен нулю.
Ошибка
Arithmetic overflow
— целочисленное переполнение — возникает
при выполнении арифметической операции
над целыми числами, когда результат
операции выходит за границы соответствующего
типа. Такая ошибка произойдет, например,
при выполнении программы
VAR
a,b : Word; c : Integer; BEGIN a:=100; b:=200; c:=a-b; END.
Ошибка
произошла, когда вычислилось значение
выражения a-b,
равное -100.
Мы знаем, что при выполнении операции
над операндами типа Word
результат будет иметь тип Word,
а -100 не является допустимым значением
этого типа. То обстоятельство, что это
значение мы собирались присвоить
переменной типа Integer,
не
имеет значения, т.к. ошибка произошла
до
присваивания. Интересно, что, если
описать a
и
b
как
Byte,
то ошибки не будет (см. таблицу 2 в главе
5).
Ошибка
Range
check error
— ошибка проверки диапазона — происходит
в двух случаях. Во-первых, при попытке
присвоить целочисленной переменной
недопустимое значение, и, во-вторых, при
использовании недопустимого индексного
выражения для элемента любого массива.
Проиллюстрируем оба эти случая на
простых примерах.
VAR
a,b,c : Word; BEGIN a:=$FFFF; b:=1; c:=a+b; END.
Мы
попытались присвоить переменной типа
Word
значение 65536, которое не является
допустимым для этого типа.
VAR
x : ARRAY[2..8] OF Real; i : Byte;
BEGIN
FOR i:=8 DOWNTO 1 DO x[i]:=Sqrt(i); END.
Ошибка
произошла при обращении к первому
элементу массива, который не существует.
Фактически этот второй случай полностью
аналогичен первому — мы попытались
«присвоить» индексу массива, тип
которого-2..8, значение 1.
Ошибка
Floating
point overflow
— вещественное переполнение — возникает
при выполнении операции над вещественными
числами, когда результат операции
слишком велик, или при попытке присвоить
вещественной переменной слишком большое
значение. Когда речь идет о вещественных
числах, термин «слишком большое»
следует понимать как большое по абсолютной
величине — знак числа не имеет значения.
Приведем пример программы, содержащей
такую ошибку.
VAR
r : Real; BEGIN r:=-1E20; r:=Sqr(r); END.
При
возведении в квадрат величины r
мы получим слишком большое для типа
Real
число
1E40.
Ошибка
Invalid
floating point operation
возникает в трех случаях:
1)
при вычислении корня из отрицательного
числа;
2)
при вычислении логарифма неположительного
числа;
3)
при вычислении функций Trunc и Round от
слишком большого (по абсолютной величине)
вещественного числа. Эта ошибка довольно
очевидна, и мы не станем ее иллюстрировать.
Как
же должен поступать программист, когда
при выполнении его программы возникают
ошибки? Прежде всего нужно локализовать
ошибку, то есть найти оператор, в котором
она произошла. В этом вам может помочь
среда Turbo Pascal, если в ней правильно
установлены опции
компилятора.
Опции компилятора позволяют изменять
режим компиляции и задаются в подменю
Compiler
меню Options
среды Turbo Pascal. Пока нас будут интересовать
лишь пять опций: Range
checking,
Stack
cheking,
I/O
checking,
Overflow
checking,
Debug
information.
Если они включены, то настройка среды
благоприятна для отладки вашей программы.
Если они выключены, то их обязательно
следует включить, а еще лучше задать их
непосредственно в тексте своей программы.
Опции записываются в программе в виде:
{$
буква
+
/ —
}
Каждой
опции соответствует своя буква (эти
буквы выделены в подменю Compiler
цветом), символ «+» означает включить,
а символ «-» — выключить. В программе
можно задать одну опцию, например, {$R+}
или несколько опций — {$R+,I-,S+}
. Некоторые опции можно записывать
только в самом начале программы, другие
могут размещаться в любом ее месте.
Опция
Range
checking
(R) отвечает за контроль ошибок Range
check error,
Overflow
checking
(C) — за контроль ошибок Ariphmetic
overflow,
I/O
cheking
(I) — за контроль ошибок ввода-вывода.
Смысл опции Stack
cheking
(S) будет объяснен несколько позже, а
опция Debug
information
(D) включает в код программы отладочную
информацию, что позволяет среде Turbo
Pascal при аварийном завершении программы
показать курсором оператор, в котором
произошла ошибка. Позаботьтесь, чтобы
при отладке программы перед первым ее
оператором была строка {$R+,C+,I+,S+,D+}
— это поможет вам найти и устранить все
ошибки. Некоторые неопытные программисты
выключают эти опции, тогда программа
не прерывается при некоторых ошибках,
а продолжает выполняться, на этом
основании делается вывод, что программа
верна. Это самообман — программа
выполняется, но выполняется неправильно
и никак не сообщает об ошибках.
Соседние файлы в папке Учебники
- #
- #
Я пытаюсь преобразовать этот код C ++ в Pascal, но я получаю ошибку 201. Может кто-нибудь помочь мне исправить это?
Код C ++:
int n;
bool a[100];
void show()
{
for (int i=1; i<=n; i++)
if (a[i])
printf("%d ", i);
printf("n");
}
void bt(int u)
{
if (u==n+1)
{
show();
return ;
}
a[u]=0;
bt(u+1);
a[u]=1;
bt(u+1);
}
main()
{
scanf("%d", &n);
bt(1);
}
Паскаль код:
type data = integer; var i,n:integer; a:array[0..100] of integer; b:array[0..100] of integer;
procedure show; var i:data; begin
for i:=1 to n do
begin
if (b[i]=0) then
writeln(a[i]);
end; end;
procedure bt(i:data); var u:data; begin
if (u=n+1) then
begin
show();
end
else
b[u]:=0;
bt(u+1);
b[u]:=1;
bt(u+1);
end;
begin
write('Nhap n ');
readln(n);
bt(1); end.
Спасибо, и извините за мой уровень английского
1
Решение
Мой c ++ немного ржавый, но это не похоже на точный перевод для меня. Попробуйте что-то вроде этого:
type
data = integer;
var
// i,
n : integer;
a : array[0..100] of boolean; // integer;
// b : array[0..100] of integer;
procedure SetUp;
var
i : Integer;
begin
for i := 0 to 100 do
a[i] := True;
end;
procedure show;
var
i : data;
begin
for i := 1 to n do
begin
if a[i] then
write(i);
end;
writeln;
end;
procedure bt(i : data);
var
u : data;
begin
if ( u = n + 1) then
begin
show();
end;
/// else
// b[u] := False;
bt(u + 1);
a[u] := True;
bt(u+1);
end;
begin
SetUp;
write('Nhap n ');
readln(n);
bt(1);
readln;
end.
Паскаль имеет родной логический тип, поэтому я изменил объявление массива a. Я включил подпрограмму SetUp для явной инициализации. Я не уверен, откуда твой массив b.
Кстати, если SetUp устанавливает значения элементов a в false, все, что вы получите, — это серия пустых строк.
1
Другие решения
Как можно более точное преобразование будет:
program StackOverflow1;
{$APPTYPE CONSOLE}
var
n: Integer;
a: array[0..99] of Boolean;
procedure show;
var
i: Integer;
begin
for i := 1 to n do // This is very suspicious!
if a[i] then
Write(i, ' ');
Writeln;
end;
procedure bt(u: Integer);
begin
if u = n + 1 then
begin
Show;
Exit;
end;
a[u] := False;
bt(u + 1);
a[u] := True;
bt(u + 1);
end;
begin
Writeln('enter n:');
Readln(n);
bt(1);
end.
Линия
for i := 1 to n do // for (int i=1; i<=n; i++)
выглядит так, как будто это должно было быть
for i := 0 to n - 1 do // for (int i=0; i<n; i++)
C не имеет проверки диапазона, поэтому он не дает вам ошибки. Но ваш Паскаль имеет, и этот цикл, вероятно, поэтому вы получаете ошибку времени выполнения 201.
Я не знаю, что должна делать эта программа, но меня не удивило бы, если бы программа на C не дала правильный результат.
Также меня не удивит, если для значений n близко к 99, вы получите ошибку переполнения стека (или эквивалентный номер времени выполнения). Если пользователь вводит значения для n > 99это, вероятно, приведет к ошибке проверки диапазона, если ошибка переполнения стека не возникнет первой.
Я пробовал с n = 80и это заняло целую вечность, поэтому я Ctrl+С‘редактировать.
В качестве альтернативы, вы можете использовать
a: array[1..100] of Boolean;
но это не соответствует программе на Си. В C все массивы начинаются с нуля. Если оригинальная программа на C работает правильно, то мой перевод на Паскаль также должен.
1
Hello I have been given the task of reading file input of 3 digit month abbreviations and a day and I must calculate the Julian date for each (sum of days since jan 1)
No matter what I do when I add two INTEGERS I get error 201 (incompatible data types). I have tried making a new program and gotten it to work but once I implement it into my existing code it doesn’t work anymore. This is very frustrating, please help. I’m sick of this stupid class making me take this language where I can’t find shit online to help.
Here is the code:
program prg6_150;
const
MONABV:array[1..12] of string[03] = ('JAN','FEB','MAR','APR','MAY','JUN',
'JUL','AUG','SEP','OCT','NOV','DEC');
MONDAYS:array[1..12] of integer = (31,28,31,30,31,30,31,31,30,31,30,31);
var
more_rec:Boolean; { EOF flag }
DAY:integer; { input day }
MONTH:string[03]; { input month abbreviation }
JULIAN:integer; { computed Julian day }
ch:char; { spacer character for input }
FileIn:Text;
FileOut:Text;
{ your module, to be called "JULIAN_DAY" inserted here }
procedure JULIAN_DAY;
var
j,sum_days:integer;
begin
j := 0;
sum_days := 0;
if MONTH = 'JAN' then j := 1 else
if MONTH = 'FEB' then j := 2 else
if MONTH = 'MAR' then j := 3 else
if MONTH = 'APR' then j := 4 else
if MONTH = 'MAY' then j := 5 else
if MONTH = 'JUN' then j := 6 else
if MONTH = 'JUL' then j := 7 else
if MONTH = 'AUG' then j := 8 else
if MONTH = 'SEP' then j := 9 else
if MONTH = 'OCT' then j := 10 else
if MONTH = 'NOV' then j := 11 else
if MONTH = 'DEC' then j := 12;
for J:= 2 to 12 do
repeat
sum_days := MONDAYS[1] + sum_days;
j := j - 1
until j = 1;
Julian := DAY + sum_days;
end;
procedure read_rec;
begin
if Eof(FileIn) then
more_rec := False
else
readln(FileIn,day,ch,month)
end; { read_rec }
procedure initialize;
begin
more_rec := True;
Assign(FileIn,'JULIAN.DAT');
Reset(FileIn);
Assign(FileOut,'JULIAN.OUT');
Rewrite(FileOut);
read_rec
end; { initialize }
procedure process;
begin
Julian_Day;
writeln(FileOut,day:2,' ',month,' ',julian:3);
read_rec
end; { process }
procedure wrapup;
begin
Close(FileOut);
Close(FileIn)
end; { wrapup }
begin { main }
initialize;
while more_rec do
process;
wrapup
end.
Command Prompt Error
Hello I have been given the task of reading file input of 3 digit month abbreviations and a day and I must calculate the Julian date for each (sum of days since jan 1)
No matter what I do when I add two INTEGERS I get error 201 (incompatible data types). I have tried making a new program and gotten it to work but once I implement it into my existing code it doesn’t work anymore. This is very frustrating, please help. I’m sick of this stupid class making me take this language where I can’t find shit online to help.
Here is the code:
program prg6_150;
const
MONABV:array[1..12] of string[03] = ('JAN','FEB','MAR','APR','MAY','JUN',
'JUL','AUG','SEP','OCT','NOV','DEC');
MONDAYS:array[1..12] of integer = (31,28,31,30,31,30,31,31,30,31,30,31);
var
more_rec:Boolean; { EOF flag }
DAY:integer; { input day }
MONTH:string[03]; { input month abbreviation }
JULIAN:integer; { computed Julian day }
ch:char; { spacer character for input }
FileIn:Text;
FileOut:Text;
{ your module, to be called "JULIAN_DAY" inserted here }
procedure JULIAN_DAY;
var
j,sum_days:integer;
begin
j := 0;
sum_days := 0;
if MONTH = 'JAN' then j := 1 else
if MONTH = 'FEB' then j := 2 else
if MONTH = 'MAR' then j := 3 else
if MONTH = 'APR' then j := 4 else
if MONTH = 'MAY' then j := 5 else
if MONTH = 'JUN' then j := 6 else
if MONTH = 'JUL' then j := 7 else
if MONTH = 'AUG' then j := 8 else
if MONTH = 'SEP' then j := 9 else
if MONTH = 'OCT' then j := 10 else
if MONTH = 'NOV' then j := 11 else
if MONTH = 'DEC' then j := 12;
for J:= 2 to 12 do
repeat
sum_days := MONDAYS[1] + sum_days;
j := j - 1
until j = 1;
Julian := DAY + sum_days;
end;
procedure read_rec;
begin
if Eof(FileIn) then
more_rec := False
else
readln(FileIn,day,ch,month)
end; { read_rec }
procedure initialize;
begin
more_rec := True;
Assign(FileIn,'JULIAN.DAT');
Reset(FileIn);
Assign(FileOut,'JULIAN.OUT');
Rewrite(FileOut);
read_rec
end; { initialize }
procedure process;
begin
Julian_Day;
writeln(FileOut,day:2,' ',month,' ',julian:3);
read_rec
end; { process }
procedure wrapup;
begin
Close(FileOut);
Close(FileIn)
end; { wrapup }
begin { main }
initialize;
while more_rec do
process;
wrapup
end.
Command Prompt Error
Maxizar писал(а):1- Используйте Lazarus.
Если уметь патчить паскалевское иде, то для многих целей оно не хуже.
2- Забудьте про атавизмы (Goto, Uses Graph, Crt). Не ну правда это даже смешно:
Лучше несколько Goto чем один указатель — структуру программы не разрушает, багов сверх меры не создаёт. Инициализация Crt весит намного меньше Sysutils, а для хелловорда от них требуется лишь Delay или Sleep. Sysutils лишь не устраивает некритичного бага при Writeln(‘русский текст в Utf8 кодировке’); Другие преимущества нужно искать с микроскопом. Sdl работает намного стабильнее Graph и в линуксе и в виндовсе, но не имеет процедур типа Line, Cirkle — того что нужно для построения графиков.
4- Я переписал программу, и она полностью работает, так в чем проблема?
Ага, работает, скомпиленная лично вами, под вайном. Лазарус 0.9.28.2 beta под линуксом не желает её компилить — отсутствует модуль Graph. Имхо, только по этой причине прогамму ещё не разложили по полочкам.
из-за чего приходится проходить весь код… у вас код 100 строк.. и пару циклов….. Дебаггер в руки и вперед.
Какой тут ещё дебаггер? При условии компиляции и запуска, здесь и без него просто ищется. Воткнуть
- Код: Выделить всё
A:=A div(A-A);
скомпилировать, запустить, посмотреть вывод, перенести вставку в другое место, скомпилить… И так до обнаружения проблемного оператора.
А автору программы можно посоветовать пореже использовать integer если нет уверенности насчёт ошибки переполнения — int64 наше всё.
Добавлено спустя 1 час 13 минут 11 секунд:
Да, вспомнил, при низкоуровневом рисовании нужно проверять координаты рисуемых точек на диапазон. Если рисовать за пределами окна, то может случиться страшное — что-то типа ошибки 201.
Я немного искал, говоря, что речь идет о хранении значения там, где оно не подходит, но я не понимаю, как это произошло в моем коде. Я проверил свой код несколько раз, но я все еще получаю это. Я немного искал, говоря, что речь идет о хранении значения там, где оно не подходит, но я не понимаю, как это произошло в моем коде. Я проверил свой код несколько раз, но я все еще получаю это.
program ACT2;
uses crt;
var
inputs : array[1..5] of integer;
index1 : integer;
choice : char;
toPrint : integer;
function getSUM(var inputArray : array of integer) : integer;
var
SUM, sumIndex : integer;
begin
SUM := 0;
sumIndex := 1;
repeat
SUM := SUM + inputArray[sumIndex];
sumIndex := sumIndex + 1;
until (sumIndex > 5);
getSUM := SUM;
end;
begin
clrscr;
for index1 := 1 to 5 do
begin
write('Input Integer[', index1); write(']: ');
readln(inputs[index1]);
end;
clrscr;
write('Integers:');
for index1 := 1 to 5 do
begin
write(' ', inputs[index1]);
end;
writeln(''); writeln(''); writeln('');
writeln('[1] SUM');
writeln('[2] AVERAGE');
writeln('');
write('INPUT: ');
readln(choice);
if(choice = '1') then
toPrint := getSUM(inputs);
writeln(toPrint);
readkey;
end.
3 ответа
Лучший ответ
Два других ответа правильно определили причину вашей проблемы, которая заключается в том, что вы используете два разных типа массива с разными основаниями, 1 против 0.
Тем не менее, вы могли бы избежать этой проблемы в первую очередь, объявив свой собственный тип целочисленного массива, а затем использовать его последовательно, как в
type
TInputArray = array[1..5] of Integer;
var
inputs : TInputArray; //array[1..5] of integer;
index1 : integer;
choice : char;
toPrint : integer;
//function getSUM(var inputArray : array of integer) : integer;
function getSUM(var inputArray : TInputArray) : integer;
var
SUM, sumIndex : integer;
begin
SUM := 0;
sumIndex := Low(inputArray);
repeat
SUM := SUM + inputArray[sumIndex];
sumIndex := sumIndex + 1;
until (sumIndex > High(inputArray));
getSUM := SUM;
end;
Обратите внимание, что целое число 5 встречается только один раз в этой версии программы, а использование стандартных функций Low и High означает, что есть только одно место, которое 5 необходимо изменить если вы хотите изменить размер массива. На самом деле, было бы лучше определить количество элементов как константу и использовать константу в объявлении массива, как в
const NumOfElements = 5;
type
TInputArray = array[1..NumOfElements] of Integer;
2
MartynA
12 Окт 2017 в 17:38
Вы делаете ошибку в своей функции GetSum.
Аргумент var inputArray : array of integer является открытым массивом, который проиндексирован с нуля.
См. Ошибки времени выполнения:
Ошибка проверки диапазона 201
Если вы скомпилировали свою программу с проверкой диапазона, вы можете получить эту ошибку в следующих случаях:
* An array was accessed with an index outside its declared range. * Trying to assign a value to a variable outside its range (for instance an enumerated type).
Здесь вы используете индекс за пределами заявленного диапазона.
Сделайте ваш цикл примерно так:
for sumIndex := 0 to High(inputArray) do ...
Это сделает функцию общей, независимой от размера массива.
2
Community
20 Июн 2020 в 09:12
В операторе функции
function getSUM(var inputArray : array of integer) : integer;
InputArray находится в открытом массиве (см. справочное руководство по FPC 14.4.5, Параметры открытого массива). Границы индекса от 0 до 4, лучше используйте low(inputArray) и high(inputArray). В вашем цикле повторения вы используете inputArray [5], где индекс 5 находится вне диапазона.
2
gammatester
11 Окт 2017 в 17:47