Задача. Пусть матрица А целых чисел размером 100*100 записана по строкам в файле. Определите, является ди она единичной.
Мне не понятно как запихнуть матрицу в типизированный файл и, самое главное, как потом проверить условие.... Помогите, пожалуйста...
volvo
26.09.2007 0:17
Цитата
как запихнуть матрицу в типизированный файл
Это какой файл? Файл целых
var f: file of integer
или файл векторов
type vector = array[1 .. 100] of integer; var f: file of vector;
? Оба - типизированные... Выбирай.
iFool
26.09.2007 0:23
Ну пусть integer... матрица получается выглядит в файле как строка?? Ввели..... а как эту самую пресловутую диагональ выделить???
volvo
26.09.2007 0:57
А тебе надо не только диагональ выделять... Надо всю таблицу проверять:
... { открываешь файл } 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 ...
Гость
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
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;
Красиво конечно, но оно не будет работать. Перебор
Это должно работать:
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
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 : 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(бонус ).
volvo
27.09.2007 15:27
Цитата(Гость @ 26.09.2007 13:15)
Volvo, можно тогда увидеть весь исходник?
Можно... В качестве бонуса Незнайке - здесь Goto на фиг не сдался, даже один, а уж тем более - два.
Вот исходник вместе с матрицей, на которой тестировался:
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
27.09.2007 16:03
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
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 тактов. Очень медленно...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.