Задача. Пусть матрица А целых чисел размером 100*100 записана по строкам в файле. Определите, является ди она единичной.
Мне не понятно как запихнуть матрицу в типизированный файл и, самое главное, как потом проверить условие.... Помогите, пожалуйста...
volvo
26.09.2007 0:17
Цитата
как запихнуть матрицу в типизированный файл
Это какой файл? Файл целых
var f: fileof integer
или файл векторов
type vector = array[1 .. 100] of integer;
var f: fileof vector;
? Оба - типизированные... Выбирай.
iFool
26.09.2007 0:23
Ну пусть integer... матрица получается выглядит в файле как строка?? Ввели..... а как эту самую пресловутую диагональ выделить???
volvo
26.09.2007 0:57
А тебе надо не только диагональ выделять... Надо всю таблицу проверять:
...
{ открываешь файл }
ok := true;
i := 1;
whilenot eof(f) dobegin
read(f, X);
if pred(i) mod (n + 1) = 0then ok := ok and (X <> 0)
else ok := ok and (X <> 1);
ifnot ok then break;
inc(i)
end;
if ok then writeln('yes')
else writeln('no');
{ закрываешь файл }
...
P.S. Понятно что N - это размер строки, т.е., в данном случае N = 100 ...
Гость
26.09.2007 1:22
А можно ещё вопрос.... как мне осуществить ввод...
Код
for i:=1 to n do for j:=1 to n do begin read(a[i,j]); write(f,a[i,j]); end;
так я думаю не правильно будет...
Горсть
26.09.2007 5:56
whilenot eof(f) dobegin
read(f, X);
if pred(i) mod (n + 1) = 0then ok := ok and (X <> 0)
else ok := ok and (X <> 1);
ifnot ok then break;
inc(i)
end;
Красиво конечно, но оно не будет работать. Перебор
Это должно работать:
whilenot eof(f) dobegin
read(f, X);
if pred(i) mod (n + 1) = 0then{ Diagonal element }
ok := X = 1else
ok := X = 0;
ifnot ok then break;
inc(i)
end;
volvo
26.09.2007 6:38
Цитата
Красиво конечно, но оно не будет работать. Перебор
Понимаешь, в чем дело... Если б оно не отработало (представь себе) - я бы не запостил это... И если ты не смог правильно это вызвать - это только твоя проблема...
Добавлено через 2 мин. P.S. Учи логические операции... В том коде, что я привел нет НИЧЕГО противоречащего ни синтаксису, ни логике...
Горсть
26.09.2007 8:43
Хорошо, например все элементы матрицы равны 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'), что совершенно неверно, так как матрица явно не единичная.
Гость
26.09.2007 18:15
Цитата(volvo @ 26.09.2007 2:38)
Понимаешь, в чем дело... Если б оно не отработало (представь себе) - я бы не запостил это...
Volvo, можно тогда увидеть весь исходник?
Neznaika
27.09.2007 15:04
Вот, что получилось у меня:
program My_TEST2; { Проверка единичной матрицы 100x100. }const
N = 100;
var
F : Fileof Integer;
I, J, K : Integer;
label
LabelMatrixIsNotE, LabelCloseFile;
beginif ParamCount <> 1thenbegin
Write('Необходимо имя файла!');
Exit
end;
Assign(F,ParamStr(1));
Reset(F);
for I := 1to N dofor J := 1to N dobegin
Read(F,K);
if (Ord(I<>J) + K) <> 1thengoto 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(бонус ).
volvo
27.09.2007 15:27
Цитата(Гость @ 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: fileof integer;
begin
assign(f, 'test.dat');
reset(f);
ok := true;
i := 1;
whilenot eof(f) dobegin
read(f, X);
if pred(i) mod (n + 1) = 0then ok := ok and (X = 1)
else ok := ok and (X = 0);
ifnot 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 dobegin ...
Neznaika
27.09.2007 16:03
volvo, так бы сразу и написали
ok := true;
i := 0;
while (not eof(f)) and ok dobegin
read(f, X);
if i mod (n + 1) = 0then
ok := X = 1else
ok := X = 0;
inc(i)
end;
а раньше было (X <>... кажется
условный оператор здесь тоже не нужен:
OK := TRUE;
I := 0;
while (not Eof(F)) and OK dobegin
Read(F, X);
OK := (Ord(I mod (N + 1) <> 0) + X) = 1;
Inc(I)
end;
P.S. Просто мне деление на каждом шаге не нравится. Кажется только через 2 года Intel обещает ускорение выполнения команд div/idiv.
volvo
27.09.2007 16:08
Цитата
условный оператор здесь тоже не нужен:
Угу... Если хочешь увеличить время работы программы - то так и сделай. Я где-то приводил тест скорости выполнения такой конструкции против If-а, полюбопытствуй...
Neznaika
27.09.2007 17:21
volvo, извините, но мне кажется, что (Ord(I<>J) + K) <> 1 быстрее чем i mod (n + 1) = 0 + if. Деление - последний оставшийся тормоз АЛУ.
Neznaika
27.09.2007 17:43
слепил тест Интересно, правда компилятор TP, для единичной матрицы лучше вариант с MOD(от volvo), для не единичной с (Ord(I<>J) + K) <> 1).
Наверно правильнее проверять на Delphi...
if также может быть преобразован в CMOV... ----------------------------------------------------------- Хмм, для TP почти нет никакой разницы.
volvo
27.09.2007 17:49
Цитата
Наверно правильнее проверять на Delphi...
Только в соответствующем разделе Я говорил именно о 16-битах... С 32-битными компиляторами кое-что меняется...
Neznaika
27.09.2007 18:26
Тьфу, чёрт! Если посмотреть в отладчике(Turbo Debugger), то можно увидеть, что при трансляции Ord(I<>J) компилятор TP использует команды условных переходов, то есть он фактически Ord превращает в IF.
Neznaika
6.10.2007 15:12
Один вопрос, volvo. Ещё неделю назад хотел спросить.
Цитата
Я говорил именно о 16-битах... С 32-битными компиляторами кое-что меняется...
Можно узнать, что Вы имеете в виду.
Turbo Debugger мне подсказал, что TP компилирует boolA := intB = intC и if intB = intC then boolA := TRUE else boolA := FALSE в почти одинаковый набор команд.
P.S. div на моём PIII выполняется за 18 тактов. Очень медленно...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.