이 페이지는 코딩도장 데이터의 읽기 전용 정적 보관본입니다.

역행렬 계산기

행렬을 입력 받았을 때 그에 해당하는 역행렬을 출력하는 코드를 작성해보세요. 추가로 행렬식이 0인경우는 따로 역행렬이 존재하지 않음을 표현해 주세요.

예시 입력
[1, 1, 1, 1]
[1, 2, 3, 4]
[2, 1, 3, 1]
[1, 0, 3, 4]

출력

[1.8, -0.8, -0.2, 0.4]

[0. 0.5, 0, -0.5]

[-1.4, 0.4, 0.6, -0.2]

[0.6, -0.1, -0.4, 0.3]

입력

[1, 1, 1]
[2, 4, 2]
[3, 3, 5]

출력

[3.5, -0.5, -0.5]

[-1, 0.5, 0]

[-1.5, 0, 0.5]

2020/01/10 15:59

농창

8개의 풀이가 있습니다.

Javascipt(ES6)...

`가우스-요르단 소거법으로 역행렬을 구함. (https://terms.naver.com/entry.nhn?docId=3338111&ref=y&cid=47324&categoryId=47324) 에서 가우스-요르단 소거법 문항 참고함.

역행렬을 구할 수 없는 경우에는 각 요소가 Infinity 혹은 NaN 으로 출력됨`;

class Matrix {
    constructor(m) {
        this.matrix = m;
        this.size = m.length;
    }

    // 역행렬 계산하여, 새로운 인스턴스 생성
    inverse_matrix() {

        // 단위행렬 identity 생성
        let identity = [];
        for(let r = 0; r < this.size; r++) {
            identity[r] = [];
            for(let c = 0; c < this.size; c++) {
                identity[r][c] = (r == c) ? 1 : 0;
            }
        }

        // 첨가행렬 augmented 생성
        let augmented = [];
        for(let r = 0; r < this.size; r++) {
            augmented[r] = [...this.matrix[r], ...identity[r]];
        }

        // 가우스-요르단 소거법으로 역행렬 계산
        for(let c = 0; c < this.size; c++) {
            for(let r = 0; r < this.size; r++) {
                if(r == c || augmented[r][c] == 0) { continue; }
                let m = augmented[c][c] / augmented[r][c];
                augmented[r] = augmented[r].map((v, i) => v * m - augmented[c][i]);
            }
        }
        for(let r = 0; r < this.size; r++) {
            let m = augmented[r][r];
            augmented[r] = augmented[r].map(v => v / m);
        }

        // augmented 에서 역행렬 inverse 에 해당하는 부분만 발췌
        let inverse = [];
        for(let r = 0; r < this.size; r++) {
            inverse[r] = augmented[r].slice(this.size);
        }

        return new Matrix(inverse);
    }

    // 행렬 출력, 소수점 4자리까지만 출력
    print_matrix() {
        let output = '';
        for(let r = 0; r < this.size; r++) {
            output += '[ ';
            for(let c = 0; c < this.size ; c++) {
                output += this.matrix[r][c].toFixed(4).replace(/\.?0*$/,'') + ((c == this.size - 1) ? ' ' : ', ');
            }
            output += ']\n';
        }

        console.log(output);
    }
}

let m_1 = [
    [1, 1, 1, 1],
    [1, 2, 3, 4],
    [2, 1, 3, 1],
    [1, 0, 3, 4],
];
new Matrix(m_1).inverse_matrix().print_matrix();

let m_2 = [
    [1, 1, 1],
    [2, 4, 2],
    [3, 3, 5],
];
new Matrix(m_2).inverse_matrix().print_matrix();

2020/01/17 11:00

tedware

n=int(input("행렬의 크기를 입력하세요:"))
q=[]       #이중리스트를 위한 도구
m=[]
for x in range(n):
    for y in range(n):
        q.append(int(input("{}행{}열 원소를 입력하세요".format(x+1,y+1))))
    m.append(q)
    q=[]
for x in range(n):
    print(m[x])
inv=[]
for x in range(n):
    for y in range(n):
        q.append(0)
    inv.append(q)
    q=[]
for x in range(n):
    inv[x][x]=1
print(inv)                       #여기까지 inv는 역행렬로변환될 항등행렬, m은 정해짐

aug=[]  #m,i의 첨가행렬
for x in range(n):
    aug.append(q)
for x in range(n):
    aug[x]=m[x]+inv[x]
print(aug)  
k=1
a=[]
b=[]   #임시저장소
'''
while aug[0][0]==0 and k != n:
    a=aug[0]
    b=aug[k]
    aug[0]=b
    aug[k]=a           #aug를 새로 정의하는거라 =으로 정의하는건안전함
    k+=1
k=1
if aug[0][0]==0:
    print("역행렬이 존재하지 않습니다.")
else:
    for x in range(1,n):
        for y in range(0,2*n):
            aug[x][y]-= (aug[x][0]/aug[0][0])*aug[0][y]
print(aug)

'''         #  첫번재 열에대한 연산... 이걸 모든행에 적용시켜야함
k=1
for t in range(n-1):
    while aug[t][t]==0 and k != n:
        a=aug[t]
        b=aug[k]
        aug[t]=b
        aug[k]=a           #aug를 새로 정의하는거라 =으로 정의하는건안전함
        k+=1
    k=t+2
    if aug[t][t]==0:
        print("역행렬이 존재하지 않습니다.")
    else:
        for x in range(t+1,n):
            c=(aug[x][t]/aug[t][t])
            for y in range(0,2*n):
                aug[x][y]-=c*aug[t][y]

                     #왜 첫열만빼는거지?       첫번재항을 수행하고나면, 첫번째 값이 바뀜. 즉 기준이 바뀌어버려서 연산결과가 달라지네... 기준을 또사용하는건 주의가필요함...
for x in range(n):
    if aug[x][x]==0:
        print("역행렬이 존재하지 않습니다.")
        break
for x in range(n):
    print(aug[x])

#이렇게하면 역삼각행렬이 나온다 여기까지만해도 역행렬의 존재여부를 파악 가능하다.
for t in range(1,n):
    for x in range(0,t):
        c=(aug[x][t]/aug[t][t])
        for y in range(0,2*n):
            aug[x][y]-=c*aug[t][y]        #대각행렬 완성
for x in range(n):
    print(aug[x])

for x in range(n):
    c=aug[x][x]
    for y in range(2*n):
        aug[x][y]/=c
for x in range(n):
    print(aug[x][n:2*n])

2020/02/10 14:35

노가다 김씨


m=[]; p=[]; inv=[]; q=[]
a=0; det=1; k=0
size = int(input("행렬의 크기:"))
for x in range(size):
    for y in range(size):
        p.append(int(input("%s행%s열 원소: " % (x+1, y+1))))
    m.append(p)
    p=[]

for x in range(size):
    for y in range(size):
        if x==y:
           q.append(1)
        else:
           q.append(0)
    inv.append(q)
    q=[]

while k<len(m):

    if m[k][k]==0:
       m = m[k+1:len(m)]+m[k:k+1]
       inv = inv[k+1:len(inv)]+inv[k:k+1]
       continue
    else:
        if m[k][k]==1:
            for i in range(k+1, len(m)):
               a = -m[i][k]
               for j in range(len(m)):
                   if a == 0:
                       break
                   m[i][j] = a*m[k][j]+m[i][j]
                   inv[i][j] = a*inv[k][j]+inv[i][j]

        else:
            a=1/m[k][k]
            for i in range(len(m)):
               m[k][i]=m[k][i]*a
               inv[k][i]=inv[k][i]*a 

            for i in range(k+1, len(m)):
               a = -m[i][k]
               for j in range(len(m)):
                    if a == 0:
                        break
                    m[i][j] = a*m[k][j]+m[i][j]
                    inv[i][j] = a*inv[k][j]+inv[i][j]
    k=k+1           


for i in range(len(m)):
    det *= m[i][i]

if det == 0:
    print('역행렬이 존재하지지 않습니다.')


else:   
   for k in range(len(m)-1, -1, -1):
        for i in range(k-1, -1, -1):
            a = -m[i][k]
            for j in range(len(m)-1, -1, -1):
               if a == 0:
                    break
               m[i][j]=a*m[k][j]+m[i][j]
               inv[i][j]=a*inv[k][j]+inv[i][j]


   for i in range(len(m)):
        for j in range(len(m)):
            inv[i][j] = '%.1f' % inv[i][j]

   for row in inv:
       print(row)

2020/03/21 21:22

정태군

import numpy as np
import numpy.linalg as li
data=[1,1,1,1,1,2,3,4,2,1,3,1,1,0,3,4]
ary=np.array(data).reshape(4,4)
try:
    print(li.inv(ary))
except:
    print("역행렬 존재 X")

2020/05/04 21:47

kim center

ㅋㅋ

2020/05/05 03:26

high hi

from copy import deepcopy
from fractions import Fraction

def bk(mat__, c, d, e) : # 기본 행변형 : d행에서 c행의 e배를 뺍니다
    for re in range(0, len(mat__)) :
        mat__[d][re] -= mat__[c][re]*e
    return deepcopy(mat__)

def ik(mat_, a, b) : # 기본 행변형 : a행과 b행을 바꿉니다
    tem = []
    tem = mat_[b]
    mat_[b] = mat_[a]
    mat_[a] = tem
    return deepcopy(mat_)

def printOut(r) : # 결과 출력
    rr = []
    for i in r :
        rr.append(deepcopy(list(map(float, i))))
    return rr


def one(mat) :
    try :        
        ## 결과를 단위행렬로서 초기화
        result = deepcopy([list(map(int, " ".join(bin(2**(len(mat)-1-i))[2:].zfill(len(mat)).split()))) for i in range(0, len(mat))])


        #계단화 할 수 있도록 행 배열 변형

        for c in range(0, len(mat)) : 
            for cc in range(c, len(mat)) :
                if mat[cc][c] != 0 :
                    mat = ik(mat, c, cc)
                    result = ik(result, c, cc)
                    break

        for ch in range(0, len(mat)) :
            if mat[ch][ch] == 0 :
                for tr in range(0, len(mat)) :
                    if mat[tr][ch] != 0 and mat[ch][tr] != 0:
                        mat = ik(mat, tr, ch)
                        result = ik(result, tr, ch)
                        break

        for ne in range(0, len(mat)) : # 행렬 대각성분을 그 크기로 나눠 1로 만듭니다
            if mat[ne][ne] != 1 :   
                alt_var = deepcopy(mat[ne][ne])
                for di in range(0, len(mat)) :
                    mat[ne][di] = Fraction(mat[ne][di], alt_var)
                    result[ne][di] = Fraction(result[ne][di], alt_var)

            for ne_ in range(0, len(mat)) : # 행변형(bk)로 각 대각성분을 제외한 자신의 열 성분이 모두 0이 되도록 합니다
                if mat[ne_][ne] != 0 and ne != ne_ :
                    alt_var_2 = deepcopy(mat[ne_][ne])
                    mat = bk(mat, ne, ne_, alt_var_2)
                    result = bk(result, ne, ne_, alt_var_2)
        return printOut(result)
    except :
        return "역행렬이 존재하지 않습니다."




if __name__ == "__main__" :
    print(one([[1, 1, 1, 1],[1, 2, 3, 4],[2, 1, 3, 1],[1, 0, 3, 4]]))
    print(one([[1, 1, 1, 1],[2, 1, 3, 1],[2, 1, 3, 1],[1, 0, 3, 4]]))
    print(one([[1, 1, 1], [2, 4, 2], [3, 3, 5]]))
    print(one([[3, 2], [3, 2]]))

결과

[[1.8, -0.8, -0.2, 0.4], [0.0, 0.5, 0.0, -0.5], [-1.4, 0.4, 0.6, -0.2], [0.6, -0.1, -0.4, 0.3]]
역행렬이 존재하지 않습니다.
[[3.5, -0.5, -0.5], [-1.0, 0.5, 0.0], [-1.5, 0.0, 0.5]]
역행렬이 존재하지 않습니다.

파이썬으로 코드 짜는게 오랜만이라서 쓸데없이 길이가 긴 느낌이네요. 다음에 시간이 나면 좀더 보기 좋게 정리해보도록 하겠습니다.

2020/08/14 14:02

GG

import numpy as np


def makeInv(n, arr):
    arr = np.linalg.inv(arr)
    for r in range(n):
        for c in range(n):
            arr[r,c] = round(arr[r,c], 2)

    return arr


#A = [[1, 1, 1, 1],[1, 2, 3, 4],[2, 1, 3, 1],[1, 0, 3, 4]]
A = [[1, 1, 1],[2, 4, 2],[3, 3, 5]]

n = len(A)
arr = np.array(A)
print(arr)
print(" ="*5, '역행렬')
print(makeInv(n, arr))

2023/07/23 21:06

insperChoi

def printArr(n, arr2):
    print('[', end='')
    for r in range(n):
        print('[', end='')
        for c in range(n):
            print('{0}'.format(arr2[r][c]), end=' ')
        if r == n-1:
            print(']]')
        else:
            print(']')
            print(end=' ')
    print()


def makeInv(n, arr):
    zArr = [[0 for j in range(n)] for i in range(n)]
    for i in range(n):
        zArr[i][i] = 1

    for s in range(n-1):
        for i in range(s, n-1):
            if arr[s][s] == 0:
                k = s+1
                while k<n-1 and arr[k][s] == 0:
                    k += 1
                for l in range(n):
                    arr[s][l], arr[k][l] = arr[k][l], arr[s][l]

            tmp = arr[i + 1][s] / arr[s][s]
            for j in range(n):
                zArr[i+1][j] -= (zArr[s][j] * tmp)
                arr[i+1][j] -= (arr[s][j] * tmp)

    for s in range(n-1, 0, -1):
        for i in range(s, 0, -1):
            tmp = arr[i - 1][s] / arr[s][s]
            for j in range(n):
                zArr[i-1][j] -= (zArr[s][j] * tmp)
                arr[i-1][j] -= (arr[s][j] * tmp)

    for i in range(n):
        for j in range(n):
            zArr[i][j] = round(zArr[i][j]/arr[i][i], 2)
            arr[i][j] /= arr[i][i]

    #printArr(n, arr)
    printArr(n, zArr)


# arr = [[1, 1, 1],[2, 4, 2],[3, 3, 5]]
# makeInv(3, arr)

arr = [[1, 1, 1, 1],[1, 2, 3, 4],[2, 1, 3, 1],[1, 0, 3, 4]]
makeInv(4, arr)

2023/07/24 14:00

insperChoi

목록으로