프로그래밍/Java

[Java] JDK 부수기 - (3) java.lang.Math

Churnobyl 2023. 12. 20. 21:55
728x90
반응형

 


java.util.Math

The class Math contains methods for performing basic numeric operations such as the elementary exponential, logarithm, square root, and trigonometric functions.

Unlike some of the numeric methods of class StrictMath, all implementations of the equivalent functions of class Math are not defined to return the bit-for-bit same results. This relaxation permits better-performing implementations where strict reproducibility is not required.

By default many of the Math methods simply call the equivalent method in StrictMath for their implementation. Code generators are encouraged to use platform-specific native libraries or microprocessor instructions, where available, to provide higher-performance implementations of Math methods. Such higher-performance implementations still must conform to the specification for Math.

Math 클래스는 기본적인 수치 계산을 수행하는 메서드들을 포함하고 있으며, 지수 함수, 로그 함수, 제곱근 그리고 삼각 함수와 같은 것들을 포함한다.
StrictMath 클래스의 수치 계산 메서드와는 다르게, Math 클래스의 메서드들은 동일한 함수에 대해 비트 단위로 완전히 일치하는  결과를 리턴하지 않는다. 이러한 완화는 엄격한 재현성이 필요하지 않은 경우 더 나은 성능을 제공할 수 있도록 한다.
기본적으로 Math 클래스의 많은 메서드들은 메서드 구현에 있어 StrictMath 클래스의 같은 메서드를 호출한다. 하지만 더 좋은 성능을 구현하기 위해 가능하면 플랫폼별 네이티브 라이브러리나 마이크로프로세서 명령을 사용할 것을 권장한다. 이러한 성능 향상 구현은 여전히 Math의 명세와 일치해야 한다.

 

 Math 클래스는 설명처럼 기본적인 수치 계산을 수행하는 메서드들을 포함하고 있다. java.lang.StrictMath 클래스는 모든 플랫폼 (Windows, iOS, Linux 등등)에서 동일한 결과를 보장하기 위해 IEEE 754 표준에 따라 동일한 알고리즘과 계산 방법을 이용해 수치 계산 메서드를 구현한 것과는 달리, Math 클래스는 성능 향상을 위한 최적화 방법으로 플랫폼에 특화된 네이티브 라이브러리나 마이크로프로세서의 명령을 일부 사용한다. 이러한 결과로 Math 클래스는 StrictMath 클래스보다 수학적 정확성은 조금 떨어지겠지만, 수학 또는 과학 관련 애플리케이션이 아닌 이상 차이는 미미하다. 따라서 대부분의 일반적인 경우에 Math 클래스를 사용하면 된다.

 

 


필드 (Fields)

제어자 및 타입
(Modifier and Type)
필드(Field) 설명(Description)
static final double E 자연 로그의 밑인 e에 가까운 double값
static final double PI  원둘레와 지름의 비율인 pi에 가까운 double값

 

 Math 클래스의 필드 상수로는 자연로그 e와 원주율 pi를 제공한다. 해당 코드는 22자리의 소숫점 값으로 되어 있다. double 자료형은 15~16자리의 정밀도를 가지지만 그것보다 더 긴 리터럴이 대입되어 있으므로 어차피 사용할 때는 double형이 표현 가능한 범위에서 적당히 반올림된다.

 

// src/java.base/java/lang/Math.java

public final class Math {
    public static final double E = 2.7182818284590452354;
    public static final double PI = 3.14159265358979323846;
}

 

 

그보다 더 정밀한 계산이 필요한 경우라면 다음의 아래의 case2처럼 쓸 수 있을 것 같다. Math.PI의 리터럴은 double형으로 캐스팅될 때 이미 적당히 반올림돼 그대로 쓸 수 없으므로 개발자가 직접 PI값을 들고 와서 계산해야 한다.

 

import java.math.BigDecimal;

public class Main {

    public static void main(String[] args) {

        // case1
        System.out.println(Math.PI + ", length : " + String.valueOf(Math.PI).length());

        System.out.println("==============================================");

        // case2
        BigDecimal bigPI = new BigDecimal("3.141592653589793238462643383279");
        bigPI = bigPI.add(new BigDecimal("123"));
        System.out.println(bigPI);
        
    }

}
3.141592653589793, length : 17
==============================================
126.141592653589793238462643383279

 

 

 


메서드 (Methods)

유형 메서드(Field) 설명(Description)
기본 산술 연산 abs(pnt** a) a의 절대값을 반환한다.
max(pnt a, pnt b), min(pnt a, pnt b) a, b의 최댓값/최솟값을 반환한다.
pow(double a, double b) a의 b거듭제곱을 반환한다.
sqrt(double a) a의 양수 루트값을 반환한다.
absExact(int/long a)
addExact(int/long x, int/long y)
subtractExact(int/long x, int/long y)
multiplyExact(int/long x, int/long y)
negateExact(int/long x)
각각 절댓값, 덧셈, 뺄셈, 곱셈, 부정의 결과를 리턴하며, 자료형의 범위를 벗어났을 경우 ArithmeticException 예외로 처리한다.
incrementExact(int/long a)
decrementExact(int/long a)
각각 1을 증가/감소한 결과를 리턴하며, 자료형의 범위를 벗어났을 경우 ArithmeticException 예외로 처리한다.
multiplyFull(int x, int y) 두 int타입 x, y의 곱셈 결과를 반환한다. 이 때 long타입으로 반환되므로 int형의 곱셈 결과가 int형 범위를 벗어날 경우에도 올바르게 계산 가능하다.
multiplyHigh(long x, long y) 두 long타입 x, y의 곱셈 결과 중 더 중요한 상위 64bit를 반환한다. 큰 숫자들의 곱셈에서 전체 결과의 크기가 long타입을 벗어나는 경우 하위 64bit보다 상위 64bit가 더 중요할 때 사용할 수 있다.
삼각 함수 관련 연산



sin(double a)
cos(double a)
tan(double a)
각각 각도 a에 대한 사인, 코사인, 탄젠트 값을 반환한다.
asin(double a)
acos(double a)
atan(double a)
각각 a에 대한 아크 사인, 아크 코사인, 아크 탄젠트를 반환한다. 이 때 반환된 각도는 각각 0.0 ~ pi, -pi/2 ~ pi/2, -pi/2 ~ pi/2범위에 있다.
atan2(double y, double x) 직각 좌표 (x, y)로부터 극 좌표 (r, θ)의 θ값을 반환한다.
sinh(double x)
cosh(double x)
tanh(double x)
각각 x값에 대한 하이퍼볼릭 사인, 하이퍼볼릭 코사인, 하이퍼볼릭 탄젠트를 반환한다.
지수 및 로그 함수




exp(double a) Euler수 e의 a 거듭제곱을 반환한다.
expm1(double x) e^x - 1을 반환한다.
log(double a) 밑이 e인 자연로그 a의 값 즉, ln a를 반환한다.
log10(double a) 밑이 10인 로그 a의 값 즉, log a를 반환한다.
log1p(double x) ln(1 + x)를 반환한다.
반올림 및 정수 변환 함수



ceil(double a) a보다 크거나 같고, 수학적 정수에 해당하는 (음의 무한대에 가장 가까운) double값을 반환한다. 올림
floor(double a) a보다 작거나 같고, 수학적 정수에 해당하는 (양의 무한대에 가장 가까운) double값을 반환한다. 내림
rint(double a) a에 가장 가까운 수학적 정수에 해당하는 double값을 반환한다.
round(float/double a) a에 가장 가까운 int/long값을 반환한다.
부동소수점 조작 및 기타 함수



copySign(float/double magnitude, float/double sign)
magnitude에 sign의 부호를 적용해 반환한다.
fma(float/double a, float/double b,  float/double c)  세 인수의 단일 곱셈-누산기(Fused multiply-add; FMA) 값을 반환한다. 즉, (a * b) + c를 수행한 후 가장 가까운 float/double로 반올림한 결과를 반환한다.
hypot(double x, double y) x^2 + y^2의 제곱근을 오버플로우나 언더플로우 없이 반환한다. 피타고라스 정리이며 hepotenuse(빗변)의 앞글자들을 따왔다.
IEEEremainder(double f1, double f2) IEEE 754 표준에 따라 f1, f2에 대한 나머지 연산의 결과를 반환한다.
nextAfter(float/double start, float/double direction)
start에서 direction방향으로 가장 인접한 부동소수점 숫자를 반환한다.
기타 함수 random() 0.0보다 크거나 같고 1.0보다 작은 랜덤값을 반환한다.

*JDK17.0.9 (2023-10-17 LTS 기준)

** pnt : primitive numeric types (원시 숫자 타입)

 

 분명 빠진 것들도 있지만 최대한 카테고리를 나눠서 정리해 보았다. 이 중에 Math클래스에서 자주 쓸 법한 메서드들은 볼드처리 했다.

반응형