자바에서 벡터를 다루는 법 (Apache.commons.math3)
아파치 수학 라이브러리를 이용하여 자바에서 벡터를 다뤄보도록 하자.
벡터란?
벡터(Vector)는 크기와 방향이 있는 성분으로, 수학이나 물리에서 사용하는 개념이다. 특히 수학을 전문적으로 다루는 프로그래밍 언어(matlab)에서도 필수적으로 등장한다.
사실 벡터는 단순하게 생각하면 행이 n개, 열이 1개인 한 줄짜리 행렬에 불과하다...
벡터는 사실 1차원 숫자 배열이다
벡터는 행이 n개, 열이 1개로 고정이 되어 있으므로 1차원 숫자 배열과 다르지 않다.
다음은 자바에서 벡터를 만드는 3가지 방법이다.
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealVector;
RealVector a = MatrixUtils.createRealVector(new double [] {1, 2, 3, 4, 5});
첫 번째, 아파치 수학 라이브러리를 사용하여 벡터 클래스를 생성하는 방법
import java.util.ArrayList;
import java.util.List;
List<Double> b = new ArrayList();
b.add(1);
b.add(2);
b.add(3);
b.add(4);
b.add(5);
두 번째, List 클래스를 이용해서 숫자 타입의 리스트를 생성하는 방법
double[] c = new double [] {1, 2, 3, 4, 5};
세 번째, 1차원 숫자 배열을 사용하는 방법
위 방법 모두 벡터를 표현할 수 있다. 하지만 제일 좋은 방법은 아파치 라이브러리의 RealVector 클래스를 사용하는 것이다.
RealVector 클래스를 사용해야 하는 이유
배열이나 List<Double>로 벡터를 표현할 수 있음에도 벡터 연산 작업에 사용하지 않는 이유는 벡터 대 상수, 혹은 벡터 대 벡터의 연산을 처리하는데 불편하기 때문이다. (불편할 뿐 구현을 못하는게 아님)
RealVector는 단위벡터 생성, 노름 계산, 요소별 연산이나 벡터연결, 벡터자르기, 요소 수정 등 편리한 기능을 지원하고 있고, 아파치 라이브러리의 선형대수학 관련 기능들이 RealVector와 RealMatrix를 중심으로 제공되기 때문에 벡터연산을 자주 해야하는 상황이라면 RealVector 사용을 고려해 볼 만 하다.
RealVector 다루기
RealVector 클래스를 이용해서 벡터를 다루는 간단한 방법과 matlab과의 비교도 해보자.
벡터 생성 방법
// in java
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealVector;
// 요소와 함께 벡터 선언
RealVector a = MatrixUtils.createRealVector(new double [] {1, 2, 3, 4, 5});
// 요소 없이 벡터 선언
RealVector b = MatrixUtils.createRealVector(new double [] {});
벡터를 생성할 때 배열 요소를 바탕으로 벡터를 생성할 수 있다. 이렇게 생성된 벡터는 matlab의
// in matlab
a = [1 2 3 4 5]
b = []
구문과 일치한다.
벡터 연산
벡터의 각 요소에 대해 연산을 쉽게 할 수 있다.
첫 번째로 벡터 대 상수 연산이다.
// in java
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealVector;
RealVector a = MatrixUtils.createRealVector(new double [] {1, 2, 3, 4, 5});
// a의 각 요소에 1을 더한 결과
// {2, 3, 4, 5, 6}
RealVector answer1 = a.mapAdd(1);
// a의 각 요소에 1을 뺀 결과
// {0, 1, 2, 3, 4}
RealVector answer2 = a.mapSubtract(1);
// a의 각 요소에 10을 곱한 결과
// {10, 20, 30, 40, 50}
RealVector answer3 = a.mapMultiply(10);
// a의 각 요소에 10을 나눈 결과
// {0.1, 0.2, 0.3, 0.4, 0.5}
RealVector answer4 = a.mapDivide(10);
위 코드는 벡터 a의 각 요소에 주어진 값을 사칙연산하는 예제이다. 이러한 연산은 matlab의
// in matlab
a = [1 2 3 4 5]
answer1 = a + 1
answer2 = a - 1
answer3 = a * 10
answer4 = a / 10
구문과 일치한다.
두 번째로 벡터 대 벡터 연산이다. 꽤 자주 사용된다.
// in java
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealVector;
RealVector a = MatrixUtils.createRealVector(new double [] {1, 2, 3, 4, 5});
RealVector b = MatrixUtils.createRealVector(new double [] {1, 2, 3, 4, 5});
// a의 각 요소에 b의 각 요소를 더한 결과
// {2, 4, 6, 8, 10}
RealVector answer1 = a.add(b);
// a의 각 요소에 b의 각 요소를 뺀 결과
// {0, 0, 0, 0, 0}
RealVector answer2 = a.subtract(1);
// a의 각 요소에 b의 각 요소를 곱한 결과
// {1, 4, 9, 16, 25}
RealVector answer3 = a.multiply(10);
// a의 각 요소에 b의 각 요소를 나눈 결과
// {1, 1, 1, 1, 1}
RealVector answer4 = a.divide(10);
위 코드는 벡터 a의 각 요소에 1대1로 매칭되는 벡터 b의 각 요소들과 사칙연산을 수행하는 예제이다. (a와 b의 길이가 같아야 함)
이러한 연산은 matlab의
// in matlab
a = [1 2 3 4 5]
b = [1 2 3 4 5]
answer1 = a + b
answer2 = a - b
answer3 = a .* 10
answer4 = a ./ 10
구문과 일치한다.
세 번째로 벡터에서 가장 크거나 작은 요소의 값이나 인덱스를 쉽게 얻을 수 있다.
// in java
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealVector;
RealVector a = MatrixUtils.createRealVector(new double [] {100, 200, 300, 400, 500});
// 4
int maxIndex = a.getMaxIndex();
// 500
double maxValue = a.a.getMaxValue();
// 0
int minIndex = a.getMinIndex();
// 100
double minValue = a.a.getMinValue();
각각 getMaxValue(), getMaxIndex(), getMinValue(), getMinIndex() 함수를 사용하면 된다.
벡터 요소 다루기
벡터에 새로운 요소를 추가하거나 수정하는 등 여러가지 방법을 알아보자.
// in java
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealVector;
RealVector a = MatrixUtils.createRealVector(new double [] {1, 2, 3, 4, 5});
// 4
double value = a.getEntry(3);
위 코드는 벡터에서 특정 인덱스에 위치한 값을 얻는 방법이다. 인덱스는 0부터 시작한다.
(참고로 matlab은 1-based indexing)
// in java
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealVector;
RealVector a = MatrixUtils.createRealVector(new double [] {1, 2, 3, 4, 5});
RealVector b = MatrixUtils.createRealVector(new double [] {6, 7, 8, 9, 10});
// {1, 2, 3, 4, 5, 100}
RealVector answer1 = a.append(100);
// {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
RealVector answer2 = a.append(b);
위 코드는 벡터에 요소를 추가하는 방법이다. 한 값을 추가할 수도 있고 다른 벡터의 요소를 전부 추가시킬 수도 있다. 즉, List의 add(), addAll() 함수와 같은 동작을 한다.
// in java
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealVector;
RealVector a = MatrixUtils.createRealVector(new double [] {1, 2, 3, 4, 5});
// {100, 2, 3, 4, 5}
a.setEntry(0, 100);
RealVector b = MatrixUtils.createRealVector(new double [] {200, 300, 400, 500});
// {100, 200, 300, 400, 500}
a.setSubVector(1, b);
// {0, 0, 0, 0, 0}
a.set(0);
위 코드는 벡터의 요소를 수정하는 방법이다.
단일 요소만 수정하고 싶을 땐 setEntry() 함수를,
벡터의 일부분을 다른 벡터의 값으로 덮어쓰고 싶을 때는 setSubVector() 함수를,
벡터의 전체 요소를 수정하고 싶을 땐 set() 함수를 사용하면 된다.
// in java
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealVector;
RealVector a = MatrixUtils.createRealVector(new double [] {1, 2, 3, 4, 5});
// {2, 3, 4}
RealVector sub = a.getSubVector(1, 3);
위 코드는 벡터를 특정 범위만큼 잘라내는 방법이다. 시작 인덱스와 잘라낼 길이를 필요로 한다. 예제에서는 인덱스 1부터 3칸 만큼 잘라낸다.
이외에도 많은 벡터를 다루는데에 필요한 많은 기능들이 제공되고 있다.
관련 문서
'Programming > Java' 카테고리의 다른 글
[Java] Java 라이브러리 패키지를 Github Actions를 이용하여 Maven central repository에 배포하는 방법 (0) | 2024.01.02 |
---|
댓글