Каким должен быть язык программирования? Анализ и критика Описание языка Компилятор
Отечественные разработки Cтатьи на компьютерные темы Компьютерный юмор Новости и прочее

Вычисление определителя матрицы. Программа на русском Си

Попалась на глаза задачка по вычислению определителя матрицы.
Вычисление определителя матрицы
Вычисление определителя матрицы на примере
Была задумка переписать её на Си на основе массивов и сравнить скорость программ. Но не срослось. Зато можно сравнить размер программ. Надо заметить, что решение на Си получилось в 2 раза короче, чем на Хаскелле.

Вот и верь потом, что Хаскелл — это язык высокого уровня с высоким уровнем абстракций. И что Си - язык даже не высокого, а среднего уровня. Выкладываю текст решения на Си. Отдельный файл с матрицей (с именем «m.c»):

#вставка  РАЗМЕР  3
// число элементов в массиве: РАЗМЕР * РАЗМЕР
двойн    M[] = { 1, 2, 3, 4, 5, 6, 7, 8, -9 };
Собственно программка:
#вставка <stdlib.h>
#вставка "m.c"	// сгенерированные константы
// ========================================================================
двойн*	Элемент (двойн  M [], _31  X, _31  Y) {
	вернуть & M [X * РАЗМЕР + Y];
};//------------------------------------------------------------
void	делить и вычесть строку (двойн  M [], _31  X, _31  Y, двойн  делитель) {
	двойн *э, *в;
	_31  №;
	для (№ = Y; № < РАЗМЕР; ++№) {
		э = & M [X * РАЗМЕР + №];
		в = & M [Y * РАЗМЕР + №];
		если (№ == Y) {
			if (X > Y) 	  // Если второй аргумент больше третьего
				*э = 0.0;
			else
				*э = 1.0; // первый элемент не делим сам на себя
		} иначе {
			*э /= делитель;
			if (X > Y) 	  // Если второй аргумент больше третьего
				*э -= *в;
	}	}
};//------------------------------------------------------------
main() {
	двойн  делитель;
	двойн  детерминант = 1.0;
	_31  слева направо;
	_31  сверху вниз;
	двойн* э;
	для (слева направо = 0; слева направо < РАЗМЕР; ++слева направо) {
	    для (сверху вниз = слева направо; сверху вниз < РАЗМЕР; ++сверху вниз) {
		делитель = * Элемент (M, сверху вниз, слева направо);
		детерминант *= делитель;
		делить и вычесть строку (M, сверху вниз, слева направо, делитель);
	    }
	}
	printf("Детерминант равен: %f", детерминант);
};
Не программка, а скромное обаяние лаконичности. А теперь сравните это с Хаскеллем:
type Row    = [Double]
type Matrix = [Row]

-- Обмен двух строк матрицы

swap :: Matrix -> Int -> Int -> Matrix
swap matrix n1 n2 = map row [0..n]
                    where n=length matrix - 1
                          row k | k==n1 = matrix !! n2
                                | k==n2 = matrix !! n1
                                | otherwise = matrix !! k

-- Вычислить строку r1+f*r2

comb :: Row -> Row -> Double -> Row
comb r1 r2 f = zipWith (\ x y -> x+f*y) r1 r2

-- прибавить к строке r1 строку r2, умноженную на f

trans :: Matrix -> Int -> Int -> Double -> Matrix
trans matrix n1 n2 f = map row [0..n]
                       where n=length matrix - 1
                             row k | k==n1 = comb (matrix !! n1) (matrix !! n2) f
                                   | otherwise = matrix !! k

-- Номер первого ненулевого в списке

getNz :: Row -> Int
getNz xs = if length tmp == 0 then (-1) else snd $ head tmp
           where tmp=dropWhile (\ (x,k) -> (abs x) <= 1.0e-10) $ zip xs [0..]

-- Поиск ведущего элемента и перестановка строк при необходимости

search :: Matrix -> Int -> Matrix
search matrix k | (abs ((matrix !! k) !! k)) > 1.0e-10 = matrix
                | nz < 0 = matrix      
                | otherwise = swap matrix k p 
                           where n   = length matrix
                                 lst = map (\ r -> r !! k) $ drop k matrix
                                 nz  = getNz lst
                                 p   = k + nz

-- получение нулей в нужном столбце

mkzero :: Matrix -> Int -> Int -> Matrix
mkzero matrix k p | p>n-1 = matrix
                  | otherwise = mkzero (trans matrix p k (-f)) k (p+1)
                    where n = length matrix
                          f = ((matrix !! p) !! k)/((matrix !! k) !! k)

-- Получение верхней треугольной формы матрицы

triangle :: Matrix -> Int -> Matrix
triangle matrix k | k>=n = matrix
                  | (abs v) <= 1.0e-10 = [[0.0]] --setz matrix k
                  | otherwise = triangle (mkzero tmp k k1) k1 
                    where n   = length matrix
                          tmp = search matrix k
                          v   = (tmp !! k) !! k
                          k1  = k+1

-- Парадная функция

gauss :: Matrix -> Matrix
gauss matrix = triangle matrix 0 

-- Произвдение диагональных элементов

proddiag :: Matrix -> Double
proddiag matrix = product $ map (\ (r,k) -> r !!k) $ zip matrix [0,1..]

-- Вычисление определителя

det :: Matrix -> Double
det matrix = proddiag $ triangle matrix 0

main = print $ det  [[1,2,3],[4,5,6],[7,8,-9]]

Опубликовано: 2012.02.01, последняя правка: 2023.11.13    23:07

ОценитеОценки посетителей
   █████████████████████ 2 (50%)
   █████████████████████ 2 (50%)
   ▌ 0
   ▌ 0

Отзывы

     2022/02/12 21:37, Gudleifr          # 

А если сравнить с нормальным ЯП?
LIST
10 DATA 15, 14, 12, 6, 7, 1, 54, 5, 7
20 DIM M(10): FOR I=0 TO 8: READ M(I): NEXT I
30 DEF FNR(X) = M(X)*M((X+1) MOD 3 + 3)*M((X+2) MOD 3 + 6)
40 DEF FNL(X) = M(X)*M((X+2) MOD 3 + 3)*M((X+1) MOD 3 + 6)
50 PRINT FNR(0)+FNR(1)+FNR(2)-FNL(0)-FNL(1)-FNL(2)
Ok
RUN
-3348
Ok

Написано со скоростью набора букв. Сколько минут уйдет времени на подгонку под нужные размеры данных (пусть даже переменные)? Две? Три?

     2022/02/14 23:35, Бурановский дедушка          # 

С таким кодом вы не пройдёте собеседование.
  • Во-первых, для другого размера матрицы надо написать другой код. Лучше, если размер матрицы будет параметром.
  • Во-вторых, он содержит «магические константы», это признак дурного тона.
  • В-третьих, код неоптимальный. Для получения единиц слева от диагонали матрицы делается деление элементов матрицы на самих себя. А ведь можно просто записать единицу без деления. Для получения нулей не надо вычитать единицу из единицы, надо просто записать ноль.
Поэтому не важно, с какой скоростью написан этот код.

Ну и «нормальным» называют язык, у которого есть нумерация строк. Из какого нафталина его вытащили? Даже мне не довелось соприкоснуться с такой стариной. Троллингом занимаемся?

     2022/02/15 00:31, Gudleifr          # 

С таким кодом вы не пройдёте собеседование.

Зато он:
1. Решает предложенную задачу.
2. Прозрачен.
3. Не содержит ошибок (за исключением опечатки OCR).

Пример "на русском Си" по этим параметрам не проходит.

Добавить свой отзыв

Написать автору можно на электронную почту
mail(аt)compiler.su

Авторизация

Регистрация

Выслать пароль

Карта сайта


Содержание

Каким должен быть язык программирования?

Анализ и критика

Описание языка

Компилятор

Отечественные разработки

Cтатьи на компьютерные темы

Компьютерный юмор

Новости и прочее

●  Политика размещения комментариев и статей

●  Предложения и замечания

●  Все голосования

●  Компьютерные ребусы и этюды для программистов

●●  Найти минимум из двух положительных целых чисел без операций сравнения

●  Утилита транслитерации русского C/C++ в стандартный

●  Решение системы уравнений методом Гаусса. Программа на русском C++

●  Вычисление определителя матрицы. Программа на русском Си




Последние отзывы

2024/04/25 21:05 ••• Ttimofeyka
Энтузиасты-разработчики компиляторов и их проекты

2024/04/23 00:00 ••• alextretyak
Признаки устаревшего языка

2024/04/21 00:00 ••• alextretyak
Постфиксные инкремент и декремент

2024/04/20 21:28 ••• Бурановский дедушка
Русский язык и программирование

2024/04/07 15:33 ••• MihalNik
Все языки эквивалентны. Но некоторые из них эквивалентнее других

2024/04/01 23:39 ••• Бурановский дедушка
Новости и прочее

2024/04/01 23:32 ••• Бурановский дедушка
Русской операционной системой должна стать ReactOS

2024/03/22 20:41 ••• void
Раскрутка компилятора

2024/03/20 19:54 ••• kt
О многократном резервировании функций

2024/03/20 13:13 ••• Неслучайный читатель
Надёжные программы из ненадёжных компонентов

2024/03/07 14:16 ••• Неслучайный читатель
«Двухмерный» синтаксис Python

2024/03/03 16:49 ••• Автор сайта
О неправомерном доступе к памяти через указатели

2024/02/28 18:59 ••• Вежливый Лис
Про лебедей, раков и щук