BCMath 임의 정밀도 수학

BCMath 임의 정밀도 수학

부동소수점은 정확한 소수 계산에 한계가 있어요. 돈이나 정밀한 계산이 필요한 값이라면, PHP에서는 BCMath를 통해 어느 크기든 정밀도까지 지정 가능한 수학을 쓸 수 있어요.

출처: BCMath Arbitrary Precision Mathematics

본문

임의 정밀도 수학(arbitrary precision mathematics)을 위해 PHP는 BCMath를 제공해요. 이 라이브러리는 메모리가 충분하다면 문자열로 표현되는, 소수점 이하 최대 2147483647(즉 0x7FFFFFFF) 자리까지 어떤 크기와 정밀도의 숫자도 지원해요.

유효한(잘 형성된) BCMath 숫자는 정규식 /^[+-]?[0-9]*(\.[0-9]*)?$/ 와 일치하는 문자열이에요.

다만 여기서 한 가지 조심할 점이 있어요. BCMath 함수가 연산자로 string을 기대하는 자리에 float를 넘기면, PHP가 floatstring으로 변환하는 방식 때문에 의도치 않은 결과가 나올 수 있어요. 문자열이 지수 표기법(BCMath가 지원하지 않는 형태)이 될 수 있고, PHP 8.0.0 이전에는 소수 구분자가 로케일에 따라 달라질 수 있기 때문이에요(BCMath는 항상 소수점을 기대해요). 예제로 확인해 볼게요.

$num1 = 0;                 // (string) 0 => '0'

$num2 = -0.000005;         // (string) -0.000005 => '-5.05E-6'

echo bcadd($num1, $num2, 6);  // => '0.000000'

setlocale(LC_NUMERIC, 'de_DE'); // 소수점 대신 쉼표를 사용

$num2 = 1.2;               // (string) 1.2 => '1,2'

echo bcsub($num1, $num2, 1);  // => '0.0'

BC Math 함수들

  • bcadd — 두 임의 정밀도 숫자를 더함
  • bcceil — 임의 정밀도 숫자를 올림
  • bccomp — 두 임의 정밀도 숫자를 비교
  • bcdiv — 두 임의 정밀도 숫자를 나눔
  • bcdivmod — 임의 정밀도 숫자의 몫과 나머지를 구함
  • bcfloor — 임의 정밀도 숫자를 내림
  • bcmod — 임의 정밀도 숫자의 나머지를 구함
  • bcmul — 두 임의 정밀도 숫자를 곱함
  • bcpow — 임의 정밀도 숫자를 거듭제곱
  • bcpowmod — 임의 정밀도 숫자를 거듭제곱하되 지정된 나머지로 축소
  • bcround — 임의 정밀도 숫자를 반올림
  • bcscale — 모든 bc 수학 함수의 기본 소수점 자리수를 설정하거나 가져옴
  • bcsqrt — 임의 정밀도 숫자의 제곱근 구하기
  • bcsub — 한 임의 정밀도 숫자를 다른 숫자에서 뺌

BcMath\Number 클래스

  • BcMath\Number — 임의 정밀도 숫자 관련 클래스
  • BcMath\Number::add — 임의 정밀도 숫자를 더함
  • BcMath\Number::ceil — 임의 정밀도 숫자를 올림
  • BcMath\Number::compare — 두 임의 정밀도 숫자를 비교
  • BcMath\Number::__construct — BcMath\Number 객체 생성
  • BcMath\Number::div — 임의 정밀도 숫자로 나눔
  • BcMath\Number::divmod — 임의 정밀도 숫자의 몫과 나머지를 구함
  • BcMath\Number::floor — 임의 정밀도 숫자를 내림
  • BcMath\Number::mod — 임의 정밀도 숫자의 나머지를 구함
  • BcMath\Number::mul — 임의 정밀도 숫자를 곱함
  • BcMath\Number::pow — 임의 정밀도 숫자를 거듭제곱
  • BcMath\Number::powmod — 임의 정밀도 숫자를 거듭제곱하되 나머지로 축소
  • BcMath\Number::round — 임의 정밀도 숫자를 반올림
  • BcMath\Number::__serialize — BcMath\Number 객체를 직렬화
  • BcMath\Number::sqrt — 임의 정밀도 숫자의 제곱근 구하기
  • BcMath\Number::sub — 임의 정밀도 숫자를 뺌
  • BcMath\Number::__toString — BcMath\Number를 문자열로 변환
  • BcMath\Number::__unserialize — data 매개변수를 BcMath\Number 객체로 역직렬화

더 알아보기

  • BCMath는 숫자를 문자열로 다뤄서 정수·소수 모두 큰 자리수에서 정확해요. 대규모 정수만 필요하다면 GMP 확장이 더 빠른 경우가 많으니 용도에 따라 골라 쓰면 돼요.