BigDecimal 클래스
BigDecimal 클래스
BigDecimal은 임의 정밀도(arbitrary-precision) 부동소수점 십진 연산을 제공해요. Ruby는 정수의 임의 정밀도 연산을 내장으로 지원하는데(42**13 같은 계산이 정확히 떨어져요), BigDecimal은 이를 크거나 정확한 부동소수점 수로 확장한 거예요.
출처: Ruby 3.3 API
본문
소개 (Introduction)
Ruby는 임의 정밀도 정수 연산을 내장 지원해요.
42**13 #=> 1265437718438866624512
BigDecimal은 아주 크거나 아주 정확해야 하는 부동소수점 수에 비슷한 지원을 해줘요. 십진 연산은 일반 계산에도 유용한데, 사람들이 기대하는 올바른 답을 주기 때문이에요 — 일반 이진 부동소수점 연산은 10진과 2진 사이의 변환 때문에 종종 미묘한 오차를 만들거든요.
예를 들어 이렇게 실행해보세요.
sum = 0
10_000.times do
sum = sum + 0.0001
end
print sum #=> 0.9999999999999062
이 결과를 BigDecimal로 계산한 결과와 비교해봐요.
require 'bigdecimal'
sum = BigDecimal("0")
10_000.times do
sum = sum + BigDecimal("0.0001")
end
print sum #=> 0.1E1
마찬가지로:
(BigDecimal("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true
(1.2 - 1.0) == 0.2 #=> false
정밀도에 관한 참고 (A Note About Precision)
BigDecimal과 다른 값을 계산할 때 결과의 정밀도는 값의 타입에 따라 달라져요.
- 값이
Float면 정밀도는Float::DIG + 1이에요. - 값이
Rational이면 정밀도는Float::DIG + 1보다 커요. - 값이
BigDecimal이면 정밀도는 내부 표현에서의 값의 정밀도로, 플랫폼 의존적이에요. - 값이 그 외 객체면 정밀도는
BigDecimal(value)변환 결과로 결정돼요.
정확한 십진 연산의 특수 값들
이진 부동소수점보다 정확한 만큼, BigDecimal은 몇 가지 특수 값이 필요해요.
무한대 (Infinity)
0으로 나누면 무한대를 돌려줘야 할 때가 있어요.
BigDecimal("1.0") / BigDecimal("0.0") #=> Infinity
BigDecimal("-1.0") / BigDecimal("0.0") #=> -Infinity
문자열 'Infinity', '+Infinity', '-Infinity'(대소문자 구분)로 무한대 수를 만들 수 있어요.
숫자 아님 (NaN)
계산 결과가 정의되지 않은 값이면 NaN(not a number)을 돌려줘요.
BigDecimal("0.0") / BigDecimal("0.0") #=> NaN
NaN은 어떤 값과도 같지 않아요. 심지어 자기 자신과도요.
n = BigDecimal('NaN')
n == 0.0 #=> false
n == n #=> false
양의 0과 음의 0
계산 결과가 현재 정밀도 한계 안에서 BigDecimal로 표현하기엔 너무 작으면 0을 돌려줘야 해요. 그 값이 음수면 음의 0을, 양수면 양의 0을 돌려줘요.
BigDecimal("1.0") / BigDecimal("-Infinity") #=> -0.0
BigDecimal("1.0") / BigDecimal("Infinity") #=> 0.0
(BigDecimal.mode로 정밀도 한계를 지정하는 방법을 참고하세요.) 비교 목적에서는 -0.0과 0.0을 같은 것으로 봐요. 수학적으로 참된 0에는 부호가 없다는 점도 참고해요.
bigdecimal/util
require 'bigdecimal/util'을 하면 BigDecimal은 물론 네이티브 Integer, Float, Rational, String 클래스에도 to_d 메서드가 생겨요.
require 'bigdecimal/util'
42.to_d # => 0.42e2
0.5.to_d # => 0.5e0
(2/3r).to_d(3) # => 0.667e0
"0.5".to_d # => 0.5e0
JSON 처리 메서드
::json_create: 주어진 객체로부터 새BigDecimal객체를 만들어요.#as_json:self를 나타내는 2요소 해시를 돌려줘요.#to_json:self를 나타내는 JSON 문자열을 돌려줘요.
이 메서드들은 JSON gem이 제공해요. 사용하려면 require 'json/add/bigdecimal' 하세요.
라이선스
Copyright © 2002 by Shigeo Kobayashi. BigDecimal은 Ruby 및 2-clause BSD 라이선스로 배포돼요. mrkn과 ruby-core 멤버들이 유지보수해요.
상수 (Constants)
| 상수 | 설명 |
|---|---|
BASE |
내부 계산에 쓰는 밑값. 32비트 시스템에서 BASE는 10000으로, 4자리씩 묶어 계산함을 나타내요(더 크면 BASE**2가 32비트에 안 들어가 두 그룹을 오버플로 없이 곱하지 못해요). |
EXCEPTION_ALL |
오버플로·언더플로·0 나눗셈이 예외를 던질지 결정해요. BigDecimal.mode 참고. |
EXCEPTION_INFINITY |
계산 결과가 무한대일 때 어떻게 할지 결정해요. BigDecimal.mode 참고. |
EXCEPTION_NaN |
계산 결과가 NaN일 때 어떻게 할지 결정해요. BigDecimal.mode 참고. |
EXCEPTION_OVERFLOW |
계산 결과가 오버플로일 때 어떻게 할지 결정해요. BigDecimal.mode 참고. |
EXCEPTION_UNDERFLOW |
계산 결과가 언더플로일 때 어떻게 할지 결정해요. BigDecimal.mode 참고. |
EXCEPTION_ZERODIVIDE |
0으로 나눌 때 어떻게 할지 결정해요. BigDecimal.mode 참고. |
INFINITY, NAN |
특수 값 상수예요. |
ROUND_CEILING |
+∞ 방향으로 반올림해요. BigDecimal.mode 참고. |
ROUND_DOWN |
0 방향으로 내림해요. BigDecimal.mode 참고. |
ROUND_FLOOR |
-∞ 방향으로 반올림해요. BigDecimal.mode 참고. |
ROUND_HALF_DOWN |
6 이상은 올리고 나머지는 내려요. BigDecimal.mode 참고. |
ROUND_HALF_EVEN |
짝수 이웃 쪽으로 반올림해요. BigDecimal.mode 참고. |
ROUND_HALF_UP |
5 이상은 올리고 나머지는 내려요. BigDecimal.mode 참고. |
ROUND_MODE |
결과를 적절한 유효 자릿수에 맞추려 반올림해야 할 때 어떻게 할지 결정해요. BigDecimal.mode 참고. |
ROUND_UP |
0에서 멀어지는 방향으로 올림해요. BigDecimal.mode 참고. |
SIGN_NEGATIVE_FINITE |
값이 음수이고 유한함을 나타내요. BigDecimal.sign 참고. |
SIGN_NEGATIVE_INFINITE |
값이 음수이고 무한함을 나타내요. BigDecimal.sign 참고. |
SIGN_NEGATIVE_ZERO |
값이 -0임을 나타내요. BigDecimal.sign 참고. |
SIGN_NaN |
값이 숫자가 아님을 나타내요. BigDecimal.sign 참고. |
SIGN_POSITIVE_FINITE |
값이 양수이고 유한함을 나타내요. BigDecimal.sign 참고. |
SIGN_POSITIVE_INFINITE |
값이 양수이고 무한함을 나타내요. BigDecimal.sign 참고. |
SIGN_POSITIVE_ZERO |
값이 +0임을 나타내요. BigDecimal.sign 참고. |
VERSION |
bigdecimal 라이브러리의 버전이에요. |
클래스 메서드 (Public Class Methods)
_load(p1)
마샬링(marshalling) 지원을 위한 내부 메서드예요. Marshal 모듈 참고.
double_fig → integer
Float 객체가 가질 수 있는 자릿수를 돌려줘요. 결과는 시스템 의존적이에요.
BigDecimal.double_fig # => 16
json_create(object)
as_json을 참고하세요.
# File ext/json/lib/json/add/bigdecimal.rb, line 13
def self.json_create(object)
BigDecimal._load object['b']
end
limit(digits)
새로 생성되는 BigDecimal 숫자의 유효 자릿수를 지정한 값으로 제한해요. BigDecimal.mode가 지정한 대로 필요에 따라 반올림해요. 기본인 0은 상한이 없음을 뜻해요. 이 메서드의 한계는 ceil, floor, truncate, round 같은 인스턴스 메서드에 지정된 한계보다 우선순위가 낮아요.
mode(mode, setting = nil) → integer
예외 처리와 반올림에 대한 모드 설정을 나타내는 정수를 돌려줘요.
예외 처리를 제어하는 모드: EXCEPTION_NaN, EXCEPTION_INFINITY, EXCEPTION_UNDERFLOW, EXCEPTION_OVERFLOW, EXCEPTION_ZERODIVIDE, EXCEPTION_ALL.
예외 설정 값:
true- 해당 모드를 true로 설정false- 해당 모드를 false로 설정nil- 모드 설정을 바꾸지 않음
BigDecimal.save_exception_mode를 쓰면 예외 모드를 잠시 바꿨다가 자동으로 복원할 수 있어요. 예시는 명확성을 위해 먼저 모든 예외 모드를 false로 두고 시작해요.
반올림 방식을 제어하는 ROUND_MODE. BigDecimal.save_rounding_mode로 잠시 바꿨다 복원할 수 있어요.
NaN 모드 — EXCEPTION_NaN은 BigDecimal NaN이 만들어질 때의 동작을 제어해요.
false(기본):BigDecimal('NaN')을 돌려줘요.true:FloatDomainError를 던져요.
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
BigDecimal('NaN') # => NaN
BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true) # => 2
BigDecimal('NaN') # Raises FloatDomainError
무한대 모드 — EXCEPTION_INFINITY는 Infinity/-Infinity가 만들어질 때 동작을 제어해요. false(기본)는 값을 돌려주고, true는 FloatDomainError를 던져요.
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
BigDecimal('Infinity') # => Infinity
BigDecimal('-Infinity') # => -Infinity
BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) # => 1
BigDecimal('Infinity') # Raises FloatDomainError
언더플로 모드 — EXCEPTION_UNDERFLOW는 언더플로가 발생할 때 동작을 제어해요. false(기본)는 BigDecimal('0') 또는 BigDecimal('-Infinity')를 돌려주고, true는 FloatDomainError를 던져요.
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
def flow_under
x = BigDecimal('0.1')
100.times { x *= x }
end
flow_under # => 100
BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) # => 4
flow_under # Raises FloatDomainError
오버플로 모드 — EXCEPTION_OVERFLOW는 오버플로가 발생할 때 동작을 제어해요. false(기본)는 BigDecimal('Infinity') 또는 BigDecimal('-Infinity')를, true는 FloatDomainError를 던져요.
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
def flow_over
x = BigDecimal('10')
100.times { x *= x }
end
flow_over # => 100
BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) # => 1
flow_over # Raises FloatDomainError
0 나눗셈 모드 — EXCEPTION_ZERODIVIDE는 0으로 나눌 때 동작을 제어해요. false(기본)는 Infinity/-Infinity를, true는 FloatDomainError를 던져요.
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
one = BigDecimal('1')
zero = BigDecimal('0')
one / zero # => Infinity
BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true) # => 16
one / zero # Raises FloatDomainError
모든 예외 — EXCEPTION_ALL은 위 전부를 제어해요.
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true) # => 23
반올림 — ROUND_MODE는 반올림 방식을 제어해요. 설정값은:
ROUND_UP: 0에서 멀어지는 방향으로 반올림. 별칭:up.ROUND_DOWN: 0 방향으로 반올림. 별칭:down,:truncate.ROUND_HALF_UP: 가장 가까운 이웃으로, 등거리면 0에서 멀어지는 방향으로. 별칭:half_up,:default.ROUND_HALF_DOWN: 가장 가까운 이웃으로, 등거리면 0 방향으로. 별칭:half_down.ROUND_HALF_EVEN(Banker's rounding): 가장 가까운 이웃으로, 등거리면 짝수 이웃으로. 별칭:half_even,:banker.ROUND_CEILING: +∞ 방향으로. 별칭:ceiling,:ceil.ROUND_FLOOR: -∞ 방향으로. 별칭:floor.
save_exception_mode { ... }
주어진 블록을 실행하되 예외 모드를 보존해요.
BigDecimal.save_exception_mode do
BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
BigDecimal(BigDecimal('Infinity'))
BigDecimal(BigDecimal('-Infinity'))
BigDecimal(BigDecimal('NaN'))
end
BigDecimal::EXCEPTION_*와 함께 쓰세요. BigDecimal.mode 참고.
save_limit { ... }
주어진 블록을 실행하되 정밀도 한계를 보존해요.
BigDecimal.limit(100)
puts BigDecimal.limit
BigDecimal.save_limit do
BigDecimal.limit(200)
puts BigDecimal.limit
end
puts BigDecimal.limit
save_rounding_mode { ... }
주어진 블록을 실행하되 반올림 모드를 보존해요.
BigDecimal.save_rounding_mode do
BigDecimal.mode(BigDecimal::ROUND_MODE, :up)
puts BigDecimal.mode(BigDecimal::ROUND_MODE)
end
BigDecimal::ROUND_*와 함께 쓰세요. BigDecimal.mode 참고.
인스턴스 메서드 (Public Instance Methods)
a % b
b로 나눈 나머지(모듈러스)를 돌려줘요. BigDecimal#divmod 참고.
*(p1)
곱셈이에요.
self ** other → bigdecimal
self를 other 거듭제곱한 BigDecimal 값을 돌려줘요.
b = BigDecimal('3.14')
b ** 2 # => 0.98596e1
b ** 2.0 # => 0.98596e1
b ** Rational(2, 1) # => 0.98596e1
관련: BigDecimal#power.
self + value → bigdecimal
self와 value의 BigDecimal 합을 돌려줘요. 정밀도 참고(Note About Precision).
b = BigDecimal('111111.111') # => 0.111111111e6
b + 2 # => 0.111113111e6
b + 2.0 # => 0.111113111e6
b + Rational(2, 1) # => 0.111113111e6
b + Complex(2, 0) # => (0.111113111e6+0i)
+big_decimal → self
self를 그대로 돌려줘요.
+BigDecimal(5) # => 0.5e1
+BigDecimal(-5) # => -0.5e1
self - value → bigdecimal
self와 value의 차를 돌려줘요.
b = BigDecimal('333333.333') # => 0.333333333e6
b - 2 # => 0.333331333e6
b - 2.0 # => 0.333331333e6
b - Rational(2, 1) # => 0.333331333e6
b - Complex(2, 0) # => (0.333331333e6+0i)
-self → bigdecimal
self의 부호를 바꾼 값을 돌려줘요.
b0 = BigDecimal('1.5')
b1 = -b0 # => -0.15e1
b2 = -b1 # => 0.15e1
a / b → bigdecimal
지정한 값으로 나눠요. 결과 정밀도는 더 큰 피연산자의 정밀도이지만, 최소 2*Float::DIG예요. BigDecimal#div, BigDecimal#quo 참고.
self < other → true or false / self <= other → true or false / self > other → true or false / self >= other → true or false
self가 other보다 작은지(또는 이하, 초과, 이상) 여부를 돌려줘요. 비교할 수 없으면 예외를 던져요.
b = BigDecimal('1.5') # => 0.15e1
b < 2 # => true
b < 2.0 # => true
b < Rational(2, 1) # => true
b < 1.5 # => false
<=>(p1)
비교 연산자예요. a <=> b는 a == b면 0, a > b면 1, a < b면 -1이에요.
==(p1) / ===(p1) / eql?(p1)
값 동등성을 검사해요. ==, ===, eql? 모두 BigDecimal에서 같은 구현이에요. 비교를 위해 값을 강제 변환할 수 있어요.
BigDecimal('1.0') == 1.0 #=> true
_dump → string
self의 마샬링을 나타내는 문자열을 돌려줘요. Marshal 모듈 참고.
inf = BigDecimal('Infinity') # => Infinity
dumped = inf._dump # => "9:Infinity"
BigDecimal._load(dumped) # => Infinity
abs → bigdecimal
self의 절댓값을 돌려줘요.
BigDecimal('5').abs # => 0.5e1
BigDecimal('-3').abs # => 0.3e1
add(value, ndigits) → new_bigdecimal
self와 value의 합을 ndigits 소수 자릿수 정밀도로 돌려줘요. ndigits가 합의 유효 자릿수보다 작으면 현재 반올림 모드(BigDecimal.mode)에 따라 그 자릿수로 반올림해요.
# 반올림 모드 설정.
BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
b = BigDecimal('111111.111')
b.add(1, 0) # => 0.111112111e6
b.add(1, 3) # => 0.111e6
b.add(1, 6) # => 0.111112e6
b.add(1, 15) # => 0.111112111e6
b.add(1.0, 15) # => 0.111112111e6
b.add(Rational(1, 1), 15) # => 0.111112111e6
as_json(*)
BigDecimal#as_json과 BigDecimal.json_create로 BigDecimal 객체를 직렬화·역직렬화할 수 있어요. as_json은 self를 직렬화해 2요소 해시를 돌려줘요.
require 'json/add/bigdecimal'
x = BigDecimal(2).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
y = BigDecimal(2.0, 4).as_json # => {"json_class"=>"BigDecimal", "b"=>"36:0.2e1"}
z = BigDecimal(Complex(2, 0)).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"}
BigDecimal.json_create는 그 해시로부터 BigDecimal 객체를 만들고, JSON.create는 역직렬화해요.
BigDecimal.json_create(x) # => 0.2e1
# File ext/json/lib/json/add/bigdecimal.rb, line 35
def as_json(*)
{
JSON.create_id => self.class.name,
'b' => _dump,
}
end
ceil(n)
값보다 크거나 같은 가장 작은 정수를 BigDecimal로 돌려줘요. n이 양수면 결과의 소수 부분이 그 자릿수를 넘지 않고, 음수면 소수점 왼쪽으로 그만큼이 0이 돼요.
BigDecimal('3.14159').ceil #=> 4
BigDecimal('-9.1').ceil #=> -9
BigDecimal('3.14159').ceil(3) #=> 3.142
BigDecimal('13345.234').ceil(-2) #=> 13400.0
clone() / dup()
복제예요.
coerce(p1)
Ruby 타입 강제 변환을 지원해요. 기본적으로 활성화돼 있지 않지만, 다른 객체가 BigDecimal로 강제 변환될 수 있으면 + * / - 같은 이항 연산을 BigDecimal과 다른 타입의 객체에 수행할 수 있어요.
a = BigDecimal("1.0")
b = a / 2.0 #=> 0.5
문자열을 BigDecimal로 강제 변환하는 것은 기본적으로 지원되지 않아요(빌드 시 특수 컴파일 옵션이 필요해요).
div(value) → integer / div(value, digits) → bigdecimal or integer
지정한 값으로 나눠요. digits를 지정하고 결과의 유효 자릿수보다 작으면 그 자릿수로 반올림해요(BigDecimal.mode 기준). digits가 0이면 / 연산자나 quo와 같아요. digits를 생략하면 결과는 정수예요(Float#div에 비유, BigDecimal#divmod 참고). BigDecimal#/, BigDecimal#quo 참고.
a = BigDecimal("4")
b = BigDecimal("3")
a.div(b, 3) # => 0.133e1
a.div(b, 0) # => 0.1333333333333333333e1
a / b # => 0.1333333333333333333e1
a.quo(b) # => 0.1333333333333333333e1
a.div(b) # => 1
divmod(value)
지정한 값으로 나눠 몫과 나머지를 BigDecimal로 돌려줘요. 몫은 -∞ 방향으로 반올림돼요.
require 'bigdecimal'
a = BigDecimal("42")
b = BigDecimal("9")
q, m = a.divmod(b)
c = q * b + m
a == c #=> true
몫 q는 (a/b).floor이고, 나머지는 q * b에 더해 a가 되도록 하는 값이에요.
exponent()
BigDecimal 숫자의 지수를 Integer로 돌려줘요. 숫자를 0.xxxxxx*10**n(xxxxxx는 앞에 0이 없는 숫자 문자열)으로 표현할 수 있다면 n이 지수예요.
finite?()
값이 유한(IS NaN도 무한도 아님)이면 true.
fix()
숫자의 정수 부분을 BigDecimal로 돌려줘요.
floor(n)
값보다 작거나 같은 가장 큰 정수를 BigDecimal로 돌려줘요. n에 관한 동작은 ceil과 같아요.
BigDecimal('3.14159').floor #=> 3
BigDecimal('-9.1').floor #=> -10
BigDecimal('3.14159').floor(3) #=> 3.141
BigDecimal('13345.234').floor(-2) #=> 13300.0
frac()
숫자의 소수 부분을 BigDecimal로 돌려줘요.
hash → integer
self의 정수 해시 값을 돌려줘요. 부호, 소수 부분, 지수가 모두 같은 두 BigDecimal만 같은 해시 값을 가져요.
infinite?()
값이 유한이면 nil, -Infinity면 -1, +Infinity면 +1을 돌려줘요.
inspect()
self의 문자열 표현을 돌려줘요.
BigDecimal("1234.5678").inspect
#=> "0.12345678e4"
modulo(b)
b로 나눈 나머지를 돌려줘요. BigDecimal#divmod 참고.
mult(other, ndigits) → bigdecimal
self와 value의 곱을 ndigits 소수 자릿수 정밀도로 돌려줘요. ndigits가 유효 자릿수보다 작으면 현재 반올림 모드로 반올림해요.
BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
b = BigDecimal('555555.555')
b.mult(3, 0) # => 0.1666666665e7
b.mult(3, 3) # => 0.167e7
b.mult(3, 6) # => 0.166667e7
b.mult(3, 15) # => 0.1666666665e7
b.mult(3.0, 0) # => 0.1666666665e7
b.mult(Rational(3, 1), 0) # => 0.1666666665e7
b.mult(Complex(3, 0), 0) # => (0.1666666665e7+0.0i)
n_significant_digits → integer
self의 십진 유효 자릿수를 돌려줘요.
BigDecimal("0").n_significant_digits # => 0
BigDecimal("1").n_significant_digits # => 1
BigDecimal("1.1").n_significant_digits # => 2
BigDecimal("3.1415").n_significant_digits # => 5
BigDecimal("-1e20").n_significant_digits # => 1
BigDecimal("1e-20").n_significant_digits # => 1
BigDecimal("Infinity").n_significant_digits # => 0
BigDecimal("-Infinity").n_significant_digits # => 0
BigDecimal("NaN").n_significant_digits # => 0
nan?()
값이 NaN이면 true.
nonzero?()
값이 0이 아니면 self, 0이면 nil을 돌려줘요.
power(n) / power(n, prec)
값을 n 거듭제곱해요. n은 Integer여야 해요. ** 연산자로도 쓸 수 있어요.
precision → integer
self의 십진 자릿수를 돌려줘요.
BigDecimal("0").precision # => 0
BigDecimal("1").precision # => 1
BigDecimal("1.1").precision # => 2
BigDecimal("3.1415").precision # => 5
BigDecimal("-1e20").precision # => 21
BigDecimal("1e-20").precision # => 20
BigDecimal("Infinity").precision # => 0
BigDecimal("-Infinity").precision # => 0
BigDecimal("NaN").precision # => 0
precision_scale → [integer, integer]
2요소 배열을 돌려줘요. 첫 항목은 BigDecimal#precision의 결과, 둘째는 BigDecimal#scale의 결과예요.
precs → array
플랫폼 의존적 내부 저장 속성을 나타내는 Integer 두 개의 배열을 돌려줘요. 더 이상 사용하지 않아요(deprecated). 과학적 표기법의 유효 자릿수는 BigDecimal#n_significant_digits, 십진 표기법의 자릿수는 BigDecimal#precision을 쓰세요.
quo(value) → bigdecimal / quo(value, digits) → bigdecimal
지정한 값으로 나눠요. digits를 지정하고 결과의 유효 자릿수보다 작으면 BigDecimal.mode의 반올림 모드에 따라 반올림해요. digits가 0이거나 생략되면 / 연산자와 같아요. BigDecimal#/, BigDecimal#div 참고.
remainder(value)
값으로 나눈 나머지를 돌려줘요. x.remainder(y)는 x-y*(x/y).truncate를 뜻해요.
round(n, mode)
기본적으로 가장 가까운 정수로 반올림해요. n을 주면 결과가 BigDecimal, 주지 않으면 Integer예요.
BigDecimal('3.14159').round #=> 3
BigDecimal('8.7').round #=> 9
BigDecimal('-9.9').round #=> -10
BigDecimal('3.14159').round(2).class.name #=> "BigDecimal"
BigDecimal('3.14159').round.class.name #=> "Integer"
n이 양수면 소수 부분이 그 자릿수를 넘지 않고, 음수면 소수점 왼쪽 그만큼이 0이 되며 반환값은 Integer예요. mode 인자로 반올림 방식을 정할 수 있어요(BigDecimal.mode 참고).
BigDecimal('3.14159').round(3) #=> 3.142
BigDecimal('13345.234').round(-2) #=> 13300
scale → integer
self에서 소수점 뒤의 자릿수를 돌려줘요.
BigDecimal("0").scale # => 0
BigDecimal("1").scale # => 0
BigDecimal("1.1").scale # => 1
BigDecimal("3.1415").scale # => 4
BigDecimal("Infinity").scale # => 0
BigDecimal("NaN").scale # => 0
sign()
값의 부호를 돌려줘요. >0이면 양수 값, <0이면 음수 값을 돌려줘요. 0에 대해서도 마찬가지로 동작해요 — 양의 0(BigDecimal('0'))은 양수 값을, 음의 0(BigDecimal('-0'))은 음수 값을 돌려줘요. 반환되는 구체적인 값은 BigDecimal의 타입과 부호를 나타내요: NaN이면 SIGN_NaN, +0이면 SIGN_POSITIVE_ZERO, -0이면 SIGN_NEGATIVE_ZERO, +Infinity면 SIGN_POSITIVE_INFINITE, -Infinity면 SIGN_NEGATIVE_INFINITE, 양수면 SIGN_POSITIVE_FINITE, 음수면 SIGN_NEGATIVE_FINITE.
split()
BigDecimal을 네 부분으로 나눠 배열로 돌려줘요.
- 첫 값은 부호로, -1 또는 1(또는 NaN이면 0)이에요.
- 둘째는 앞에 0이 없는 유효 숫자 문자열이에요.
- 셋째는 연산에 쓰는 밑(현재 항상 10)의 Integer예요.
- 넷째는 Integer 지수예요.
0.xxxxxx*10**n으로 표현된다면 xxxxxx가 유효 숫자 문자열이고 n이 지수예요. 이 값들로 BigDecimal을 float로 변환할 수 있어요.
sign, significant_digits, base, exponent = a.split
f = sign * "0.#{significant_digits}".to_f * (base ** exponent)
(BigDecimal을 Float로 변환하는 더 편리한 방법은 to_f 메서드예요.)
sqrt(n)
값의 제곱근을 돌려줘요. 결과는 적어도 n개의 유효 자릿수를 가져요.
sub(value, digits) → bigdecimal
지정한 값을 뺄셈해요. digits를 지정하고 결과의 유효 자릿수보다 작으면 BigDecimal.mode에 따라 반올림해요.
c = a.sub(b,n)
to_d → bigdecimal
self를 돌려줘요.
require 'bigdecimal/util'
d = BigDecimal("3.14")
d.to_d # => 0.314e1
# File ext/bigdecimal/lib/bigdecimal/util.rb, line 110
def to_d
self
end
to_digits → string
BigDecimal을 "nnnnnn.mmm" 형태의 문자열로 변환해요. 더 이상 사용하지 않아요(deprecated); BigDecimal#to_s("F")를 쓰세요.
require 'bigdecimal/util'
d = BigDecimal("3.14")
d.to_digits # => "3.14"
to_f()
BigDecimal과 대략 같은 값을 갖는 새 Float 객체를 돌려줘요. 이진 Float 연산의 일반적인 정밀도 한계와 내장 오차가 적용돼요.
to_i() / to_int()
값을 Integer로 돌려줘요. BigDecimal이 무한대나 NaN이면 FloatDomainError를 던져요.
to_json(*args)
self를 나타내는 JSON 문자열을 돌려줘요.
require 'json/add/bigdecimal'
puts BigDecimal(2).to_json
# {"json_class":"BigDecimal","b":"27:0.2e1"}
# File ext/json/lib/json/add/bigdecimal.rb, line 55
def to_json(*args)
as_json.to_json(*args)
end
to_r()
BigDecimal을 Rational로 변환해요.
to_s(s)
값을 문자열로 변환해요. 기본 형식은 0.xxxxEnn이에요. 선택 인자 s는 정수 하나이거나, 선택적 '+'나 ' ' 뒤에 선택적 숫자, 선택적 'E'나 'F'로 구성돼요.
s시작에'+'가 있으면 양수 값 앞에'+'가 붙어요.s시작에 공백이 있으면 양수 값 앞에 공백이 붙어요.s에 숫자가 있으면 소수점부터 바깥으로 세면서 그 자릿수마다 공백이 들어가요.s가'E'로 끝나면 공학 표기법(0.xxxxEnn)을 쓰고,'F'로 끝나면 일반 부동소수점 표기법을 써요.
BigDecimal('-1234567890123.45678901234567890').to_s('5F')
#=> '-123 45678 90123.45678 90123 45678 9'
BigDecimal('1234567890123.45678901234567890').to_s('+8F')
#=> '+12345 67890123.45678901 23456789'
BigDecimal('1234567890123.45678901234567890').to_s(' F')
#=> ' 1234567890123.4567890123456789'
truncate(n)
기본적으로 가장 가까운 정수로 자르고 결과를 BigDecimal로 돌려줘요. n에 관한 동작은 ceil과 같아요.
BigDecimal('3.14159').truncate #=> 3
BigDecimal('8.7').truncate #=> 8
BigDecimal('-9.9').truncate #=> -9
BigDecimal('3.14159').truncate(3) #=> 3.141
BigDecimal('13345.234').truncate(-2) #=> 13300.0
zero?()
값이 0이면 true.
더 알아보기
require 'bigdecimal/math'로BigMath모듈의 고정밀 삼각함수·지수·로그 함수를 쓸 수 있어요.bigdecimal/util의to_d로 일반 숫자·문자열을 BigDecimal로 쉽게 변환할 수 있어요.