Помощь - Поиск - Пользователи - Календарь
Полная версия: Матрица в типизированном файле
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
iFool
Задача.
Пусть матрица А целых чисел размером 100*100 записана по строкам в файле. Определите, является ди она единичной.

Мне не понятно как запихнуть матрицу в типизированный файл и, самое главное, как потом проверить условие....
Помогите, пожалуйста...
volvo
Цитата
как запихнуть матрицу в типизированный файл
Это какой файл? Файл целых
var f: file of integer

или файл векторов
type vector = array[1 .. 100] of integer;
var f: file of vector;
? Оба - типизированные... Выбирай.
iFool
Ну пусть integer...
матрица получается выглядит в файле как строка??
Ввели..... а как эту самую пресловутую диагональ выделить???
volvo
А тебе надо не только диагональ выделять... Надо всю таблицу проверять:

...
{ открываешь файл }
ok := true;
i := 1;
while not eof(f) do begin

read(f, X);
if pred(i) mod (n + 1) = 0 then ok := ok and (X <> 0)
else ok := ok and (X <> 1);

if not ok then break;
inc(i)
end;

if ok then writeln('yes')
else writeln('no');
{ закрываешь файл }
...


P.S. Понятно что N - это размер строки, т.е., в данном случае N = 100 ...
Гость
А можно ещё вопрос....
как мне осуществить ввод...
Код

for i:=1 to n do
     for j:=1 to n do
       begin
         read(a[i,j]);
         write(f,a[i,j]);
       end;

так я думаю не правильно будет...
Горсть

while not eof(f) do begin

read(f, X);
if pred(i) mod (n + 1) = 0 then ok := ok and (X <> 0)
else ok := ok and (X <> 1);


if not ok then break;
inc(i)
end;


Красиво конечно, но оно не будет работать. Перебор blink.gif

Это должно работать:

while not eof(f) do begin

read(f, X);

if pred(i) mod (n + 1) = 0 then { Diagonal element }
ok := X = 1
else
ok := X = 0;

if not ok then break;
inc(i)
end;


volvo
Цитата
Красиво конечно, но оно не будет работать. Перебор
Понимаешь, в чем дело... Если б оно не отработало (представь себе) - я бы не запостил это... И если ты не смог правильно это вызвать - это только твоя проблема... dry.gif

Добавлено через 2 мин.
P.S. Учи логические операции... В том коде, что я привел нет НИЧЕГО противоречащего ни синтаксису, ни логике...
Горсть
Хорошо, например все элементы матрицы равны 2.
Тогда ok := ok and (X <> 0) == ok and (2 <> 0) = ok and TRUE = ok
и
ok := ok and (X <> 1) == ok and (2 <> 1) = ok and TRUE = ok
Так как до while ok=TRUE, то в данном случае после while также будет ok=TRUE
и далее writeln('yes'), что совершенно неверно, так как матрица явно не единичная.
Гость
Цитата(volvo @ 26.09.2007 2:38) *

Понимаешь, в чем дело... Если б оно не отработало (представь себе) - я бы не запостил это...

Volvo, можно тогда увидеть весь исходник?
Neznaika
Вот, что получилось у меня:

program My_TEST2; { Проверка единичной матрицы 100x100. }
const
N = 100;
var
F : File of Integer;
I, J, K : Integer;
label
LabelMatrixIsNotE, LabelCloseFile;
begin
if ParamCount <> 1 then
begin
Write('Необходимо имя файла!');
Exit
end;
Assign(F,ParamStr(1));
Reset(F);
for I := 1 to N do
for J := 1 to N do
begin
Read(F,K);
if (Ord(I<>J) + K) <> 1 then
goto LabelMatrixIsNotE
end;
Write('Матрица единичная.');
goto LabelCloseFile;
LabelMatrixIsNotE:
Write('Матрица НЕ единичная!');
LabelCloseFile:
Close(F)
end.



Объяснение "(Ord(I<>J) + K) <> 1":
I и J изменяются от 1 до 100. Для диагональных элементов матрицы I = J. K - соответствующий элемент матрицы.
Возможны два ПРАВИЛЬНЫХ варианта:
1) I = J, K = 1.
2) I <> J, K = 0.
Первые условия могут быть либо TRUE, либо FALSE и отрицают друг друга.
Пусть (I=J) будет эквивалентно FALSE, тогда (I<>J) будет эквивалентно TRUE. Получим
1) FALSE, K = 1.
2) TRUE, K = 0.
Здесь уже видна СИММЕТРИЯ(которая собственно и нужна для создания подобных выражений), а именно
порядковые номера FALSE и TRUE равны соответственно 0 и 1(Ord(FALSE) = 0, Ord(TRUE) = 1). Получили
1) 0, K = 1.
2) 1, K = 0.
Видно, что когда матрица ЕДИНИЧНАЯ, то (0 + 1) = (1 + 0) = 1. Когда матрица НЕ ЕДИНИЧНАЯ, то
складывая 0(для 1)) или 1(для 2)) с K получить 1 не удастся. Следовательно
if (Ord(I<>J) + K) <> 1 then МАТРИЦА НЕ ЕДИНИЧНАЯ

В архиве простенькая программа генерации единичной матрицы и программа "простой" проверки(My_TEST1).

P.S.
Так используются два цикла for и оба они прерываются при первой ошибке(при появлении первого "неправильного" элемента матрицы), Break для выхода из циклов применить нельзя, поэтому
используется оператор GOTO. Даже целых два GOTO(бонус smile.gif ).
volvo
Цитата(Гость @ 26.09.2007 13:15) *

Volvo, можно тогда увидеть весь исходник?

Можно... В качестве бонуса Незнайке - здесь Goto на фиг не сдался, даже один, а уж тем более - два.

Вот исходник вместе с матрицей, на которой тестировался:
(*
const
n = 10;
arr: array[1 .. n * n] of integer = (
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1
);
*)
var
i, X: integer;
ok: boolean;
f: file of integer;
begin
assign(f, 'test.dat');
reset(f);

ok := true;
i := 1;
while not eof(f) do begin

read(f, X);
if pred(i) mod (n + 1) = 0 then ok := ok and (X = 1)
else ok := ok and (X = 0);

if not ok then break;
inc(i)
end;

if ok then writeln('yes')
else writeln('no');

close(f);

end.



Добавлено через 4 мин.
Кстати, можно и вообще без Break-а обойтись:

while (not eof(f)) and ok do begin ...
Neznaika
volvo, так бы сразу и написали

ok := true;
i := 0;
while (not eof(f)) and ok do begin

read(f, X);
if i mod (n + 1) = 0 then
ok := X = 1
else
ok := X = 0;
inc(i)
end;


а раньше было (X <>... кажется

условный оператор здесь тоже не нужен:

OK := TRUE;
I := 0;
while (not Eof(F)) and OK do
begin
Read(F, X);
OK := (Ord(I mod (N + 1) <> 0) + X) = 1;
Inc(I)
end;



P.S.
Просто мне деление на каждом шаге не нравится.
Кажется только через 2 года Intel обещает ускорение выполнения команд div/idiv.
volvo
Цитата
условный оператор здесь тоже не нужен:
Угу... Если хочешь увеличить время работы программы - то так и сделай. Я где-то приводил тест скорости выполнения такой конструкции против If-а, полюбопытствуй...
Neznaika
volvo, извините, но мне кажется, что (Ord(I<>J) + K) <> 1 быстрее чем i mod (n + 1) = 0 + if.
Деление - последний оставшийся тормоз АЛУ.
Neznaika
слепил тест
Интересно, правда компилятор TP, для единичной матрицы лучше вариант с MOD(от volvo),
для не единичной с (Ord(I<>J) + K) <> 1).

Наверно правильнее проверять на Delphi...

if также может быть преобразован в CMOV...
-----------------------------------------------------------
Хмм, для TP почти нет никакой разницы.
volvo
Цитата
Наверно правильнее проверять на Delphi...
Только в соответствующем разделе smile.gif Я говорил именно о 16-битах... С 32-битными компиляторами кое-что меняется...
Neznaika
Тьфу, чёрт!
Если посмотреть в отладчике(Turbo Debugger), то можно увидеть, что
при трансляции Ord(I<>J) компилятор TP использует команды условных переходов,
то есть он фактически Ord превращает в IF.
Neznaika
Один вопрос, volvo. Ещё неделю назад хотел спросить.
Цитата
Я говорил именно о 16-битах... С 32-битными компиляторами кое-что меняется...

Можно узнать, что Вы имеете в виду.

Turbo Debugger мне подсказал, что TP компилирует
boolA := intB = intC и if intB = intC then boolA := TRUE else boolA := FALSE
в почти одинаковый набор команд.

P.S.
div на моём PIII выполняется за 18 тактов. Очень медленно...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.