이상엽 선형대수학 정수행 3회차 - 벡터의 기본
2023. 3. 22. 12:36ㆍ선형대수학
1. 용어 정리
- 벡터: n차원의 공간에서 방향과 크기를 표현하는 도구
- 평면 벡터: 2차원 공간에서의 벡터
- 공간 벡터: 3차원 공간에서의 벡터
- 스칼라(Scalar) 혹은 노름(Norm): 벡터의 크기
- 정규화(Normalization): 벡터의 크기를 1로 맞춰주는 것
- 법선벡터(Normal Vector): 어떤 평면의 수직인 벡터
- 영벡터(Zero Vector): 크기가 0인 벡터 (원래 다른 방법으로 영벡터로 표기하지만 표기상의 문제로 지금부터 쓰는 모든 게시글에서는 0v로 표기함)
- 위치벡터(Position Vector): 원점으로부터 시작하는 벡터
- 단위벡터(Unit Vector): 크기가 1인 벡터. 벡터의 각 원소에 스칼라를 나눠서 구한다.
2. 선형 결합
위키 백과에 따르면 "각 항에 상수를 곱하고 결과를 더함으로써 일련의 항으로 구성된 표현식" 이라고 이야기하고 있는데 어떤 벡터를 나타내는데 다른 벡터들의 스칼라 배와 합으로 나타내면 그것을 선형 결합이라고 한다. 강의에서는 선형 결합을 언급한 후에 벡터의 연산으로 넘어갔는데 아래에 그 내용을 설명하겠다.
- 덧셈: A(a1, a2, ... , an) + B(b1, b2, ... , bn) = (a1 + b1, a2 + b2, ... , an + bn)
- 뺄셈: A(a1, a2, ... , an) - B(b1, b2, ... , bn) = (a1 - b1, a2 - b2, ... , an - bn)
- 내적: A(a1, a2, ... , an) ● B(b1, b2, ... , bn) = (a1 x b1, a2 x b2, ... , an x bn) = ||A|| x ||B|| x cos𝜽
- 외적: A(a1, a2, a3) x B(b1, b2, b3) = ( det( [a2, a3], [b2, b3] ), det( [a1, a3], [b1, b3] ), det( [a1, a2], [b1, b2] ) )
내적 연산을 하는 방법으로 2가지를 써놓았다. 두 벡터의 크기와 cos𝜽를 곱하는 방법과 각 항을 서로 곱하는 방법인데 각 항을 서로 곱했을 때, 어떻게 그것이 내적의 결과로 나오는지는 제2 코사인 법칙으로 증명이 가능하지만 이 글에서는 생략하도록 하겠다.
외적의 결과로 나오는 벡터는 앙페르의 오른나사 법칙을 떠올리면 이해하기 쉽다. 두 벡터의 수직인 벡터는 사실상 어떤 평면의 법선 벡터를 의미하는데 3차원 공간이라면 두 개의 방향이 나오게 되기 때문에 앙페르의 오른나사 법칙을 기억하고 이곳에 적용시키면 헷갈리지 않고 외적에서 나오는 벡터의 방향을 그림으로 쉽게 알 수 있다.
참고로 내적과 외적은 둘 다 벡터의 곱으로 불리지만 차이점이 명확하게 존재하며 회사 면접으로 거의 필수적으로 나오는 단골 질문이기 때문에 이해를 해놓는 것이 좋다. 이해가 안가면 외워서라도 숙지해야 한다.
- 기하학적 차이: 내적은 두 벡터가 서로에게 얼마만큼의 힘을 행사하고 있는가를 나타내는 반면, 외적은 두 벡터와 동시에 수직인 법선 벡터를 의미한다. 외적으로 나오는 벡터는 두 벡터로 만들 수 있는 평행사변형의 면적의 넓이와 같다.
- 결과의 차이: 내적은 하나의 값. 즉, 스칼라(벡터의 크기)가 반환되는 반면 외적은 법선 벡터 즉, 벡터 자체를 반환한다.
- 연산이 가능한 경우의 차이: 내적 연산은 모든 차원에서 가능하지만 외적은 3차원 공간에서만 가능하다.
- 결합 법칙, 교환 법칙의 차이: 내적은 벡터끼리 결합 법칙과 교환 법칙이 통하지만 외적은 그것이 불가능하다. 교환 법칙을 적용할 경우에는 부호가 반대로 바뀌게 된다. 기하학적으로 이해를 하면 당연해질 것이다.
3. 구현
Vector.h
#ifndef __VECTOR_H__
#define __VECTOR_H__
#include <initializer_list>
class Vector
{
public:
Vector(const Vector& vector);
Vector(const std::initializer_list<float>& elements);
~Vector();
public:
static Vector CreateZeroVector(size_t degree);
int GetDegree() const;
float GetScalar() const;
Vector GetCrossProduct(const Vector& vector) const;
Vector Normalization() const;
public:
Vector& operator=(const Vector& vector);
Vector operator+(const Vector& vector) const;
Vector operator-(const Vector& vector) const;
float operator*(const Vector& vector) const;
Vector operator*(float coef) const;
Vector operator/(float coef) const;
friend Vector operator*(float coef, const Vector& vector);
friend Vector operator/(float coef, const Vector& vector);
Vector& operator+=(const Vector& vector);
Vector& operator-=(const Vector& vector);
Vector& operator*=(float coef);
Vector& operator/=(float coef);
float& operator[](int i);
float operator[](int i) const;
private:
float* elements;
int degree;
};
#endif
Vector.cpp
#include "Vector.h"
#include <cassert>
#include <cmath>
#include <iostream>
using namespace std;
Vector::Vector(const Vector& vector)
{
degree = vector.degree;
elements = new float[degree];
for (int i = 0; i < degree; ++i)
{
elements[i] = vector.elements[i];
}
}
Vector::Vector(const std::initializer_list<float>& elements)
{
degree = elements.size();
this->elements = degree > 0 ? new float[degree] : nullptr;
int i = 0;
for (float element : elements)
{
this->elements[i] = element;
++i;
}
}
Vector::~Vector()
{
delete[] elements;
}
Vector Vector::CreateZeroVector(size_t degree)
{
Vector zeroVector = { };
zeroVector.degree = degree;
zeroVector.elements = new float[degree];
for (int i = 0; i < degree; ++i)
{
zeroVector.elements[i] = 0.0f;
}
return zeroVector;
}
int Vector::GetDegree() const
{
return degree;
}
float Vector::GetScalar() const
{
float total = 0.0f;
for (int i = 0; i < degree; ++i)
{
total += elements[i] * elements[i];
}
return sqrtf(total);
}
Vector Vector::GetCrossProduct(const Vector& vector) const
{
assert(degree == 3 && vector.degree, "To take the cross product, the vectors must be three-dimensional.");
Vector ret = *this;
for (int i = 0; i < degree; ++i)
{
ret[i] = (elements[(i + 1) % degree] * vector[(i + 2) % degree])
- (elements[(i + 2) % degree] * vector[(i + 1) % degree]);
}
return ret;
}
Vector Vector::Normalization() const
{
return *this / GetScalar();
}
Vector& Vector::operator=(const Vector& vector)
{
assert(degree == vector.degree, "Cannot be performed due to different orders.");
for (int i = 0; i < degree; ++i)
{
elements[i] = vector[i];
}
return *this;
}
Vector Vector::operator+(const Vector& vector) const
{
assert(degree == vector.degree, "Cannot be performed due to different orders.");
Vector ret = *this;
for (int i = 0; i < degree; ++i)
{
ret[i] += vector[i];
}
return ret;
}
Vector Vector::operator-(const Vector& vector) const
{
assert(degree == vector.degree, "Cannot be performed due to different orders.");
Vector ret = *this;
for (int i = 0; i < degree; ++i)
{
ret[i] -= vector[i];
}
return ret;
}
float Vector::operator*(const Vector& vector) const
{
float total = 0.0f;
for (int i = 0; i < degree; ++i)
{
total += elements[i] * vector.elements[i];
}
return total;
}
Vector Vector::operator*(float coef) const
{
Vector vector = *this;
for (int i = 0; i < degree; ++i)
{
vector[i] *= coef;
}
return vector;
}
Vector Vector::operator/(float coef) const
{
Vector vector = *this;
for (int i = 0; i < degree; ++i)
{
vector[i] /= coef;
}
return vector;
}
Vector operator*(float coef, const Vector& vector)
{
Vector ret = vector;
for (int i = 0; i < ret.degree; ++i)
{
ret[i] *= coef;
}
return ret;
}
Vector operator/(float coef, const Vector& vector)
{
Vector ret = vector;
for (int i = 0; i < ret.degree; ++i)
{
ret[i] /= coef;
}
return ret;
}
Vector& Vector::operator+=(const Vector& vector)
{
*this = *this + vector;
return *this;
}
Vector& Vector::operator-=(const Vector& vector)
{
*this = *this - vector;
return *this;
}
Vector& Vector::operator*=(float coef)
{
*this = *this * coef;
return *this;
}
Vector& Vector::operator/=(float coef)
{
*this = *this / coef;
return *this;
}
float& Vector::operator[](int i)
{
return elements[i];
}
float Vector::operator[](int i) const
{
return elements[i];
}
'선형대수학' 카테고리의 다른 글
이상엽 선형대수학 정주행 5회차 - 선형사상 (0) | 2023.03.26 |
---|---|
이상엽 선형대수학 정주행 4회차 - 대수구조와 벡터 (0) | 2023.03.24 |
이상엽 선형대수학 정주행 2회차 - 행렬식과 역행렬 (0) | 2023.03.20 |
이상엽 선형대수학 정주행 1회차 - 행렬의 기본 (0) | 2023.03.19 |
이상엽 선형대수학 정주행 - Intro (0) | 2023.03.18 |