Rational 클래스

Rational 클래스

유리수(rational number)는 두 정수의 쌍, 즉 a/b (b>0)로 나타낼 수 있는데, 여기서 a를 분자(numerator), b를 분모(denominator)라고 불러요. 수학적으로 정수 a는 유리수 a/1과 같아요.

출처: Ruby 4.0 API

본문

Rational 객체는 두 가지로 만들 수 있어요.

  • 유리수 리터럴로 직접 만들기
  • Rational 메서드로 특정 객체를 변환하기
Rational(1)      #=> (1/1)
Rational(2, 3)   #=> (2/3)
Rational(4, -6)  #=> (-2/3) # Reduced.
3.to_r           #=> (3/1)
2/3r             #=> (2/3)

부동소수점 수나 문자열에서도 유리수 객체를 만들 수 있어요.

Rational(0.3)    #=> (5404319552844595/18014398509481984)
Rational('0.3')  #=> (3/10)
Rational('2/3')  #=> (2/3)

0.3.to_r         #=> (5404319552844595/18014398509481984)
'0.3'.to_r       #=> (3/10)
'2/3'.to_r       #=> (2/3)
0.3.rationalize  #=> (3/10)

유리수 객체는 정확한(exact) 수예요. 그래서 반올림 오류 없이 프로그램을 작성하는 데 도움이 돼요.

10.times.inject(0) {|t| t + 0.1 }              #=> 0.9999999999999999
10.times.inject(0) {|t| t + Rational('0.1') }  #=> (1/1)

다만, 표현식 안에 부정확한(inexact) 성분(숫자 값이나 연산)이 섞이면 결과도 부정확해져요.

Rational(10) / 3   #=> (10/3)
Rational(10) / 3.0 #=> 3.3333333333333335

Rational(-8) ** Rational(1, 3)
                   #=> (1.0000000000000002+1.7320508075688772i)

Public Class Methods

json_create(object)

as_json을 참고하세요. JSON에서 Rational 객체를 복원해요.

Public Instance Methods

self * other → numeric

selfother의 곱을 반환해요:

Rational(9, 8)  * 4               #=> (9/2)
Rational(20, 9) * 9.8             #=> 21.77777777777778
Rational(9, 8)  * Complex(1, 2)   # => ((9/8)+(9/4)*i)
Rational(2, 3)  * Rational(2, 3)  #=> (4/9)
Rational(900)   * Rational(1)     #=> (900/1)
Rational(-2, 9) * Rational(-9, 2) #=> (1/1)

self ** exponent → numeric

selfexponent만큼 거듭제곱한 값을 반환해요:

Rational(2)    ** Rational(3)     #=> (8/1)
Rational(10)   ** -2              #=> (1/100)
Rational(10)   ** -2.0            #=> 0.01
Rational(-4)   ** Rational(1, 2)  #=> (0.0+2.0i)
Rational(1, 2) ** 0               #=> (1/1)
Rational(1, 2) ** 0.0             #=> 1.0

self + other → numeric

selfother의 합을 반환해요:

Rational(2, 3) + 0  # => (2/3)
Rational(2, 3) + 1  # => (5/3)
Rational(2, 3) + -1 # => (-1/3)

Rational(2, 3) + Complex(1, 0)     # => ((5/3)+0i)

Rational(2, 3) + Rational(1, 1)     # => (5/3)
Rational(2, 3) + Rational(3, 2)     # => (13/6)
Rational(2, 3) + Rational(3.0, 2.0) # => (13/6)
Rational(2, 3) + Rational(3.1, 2.1) # => (30399297484750849/14186338826217063)

Float가 포함된 계산은 결과가 부정확할 수 있어요 (Float#+ 참고):

Rational(2, 3) + 1.0 # => 1.6666666666666665
Rational(2, 3) + Complex(1.0, 0.0) # => (1.6666666666666665+0.0i)

self - other → numeric

selfother의 차를 반환해요:

Rational(2, 3)  - Rational(2, 3)   #=> (0/1)
Rational(900)   - Rational(1)      #=> (899/1)
Rational(-2, 9) - Rational(-9, 2)  #=> (77/18)
Rational(9, 8)  - 4                #=> (-23/8)
Rational(20, 9) - 9.8              #=> -7.577777777777778

-self → rational

self를 부정(negate)한 값을 반환해요:

-(1/3r)   # => (-1/3)
-(-1/3r)  # => (1/3)

self / other → numeric

selfother의 몫을 반환해요:

Rational(2, 3)  / Rational(2, 3)   #=> (1/1)
Rational(900)   / Rational(1)      #=> (900/1)
Rational(-2, 9) / Rational(-9, 2)  #=> (4/81)
Rational(9, 8)  / 4                #=> (9/32)
Rational(20, 9) / 9.8              #=> 0.22675736961451246

self <=> other → -1, 0, 1, or nil

selfother를 비교해요. 반환값은 다음과 같아요:

  • -1: self가 other보다 작을 때
  • 0: 두 값이 같을 때
  • 1: self가 other보다 클 때
  • nil: 두 값을 비교할 수 없을 때
Rational(2, 3) <=> Rational(4, 3) # => -1
Rational(2, 1) <=> Rational(2, 1) # => 0
Rational(2, 1) <=> 2              # => 0
Rational(2, 1) <=> 2.0            # => 0
Rational(2, 1) <=> Complex(2, 0)  # => 0
Rational(4, 3) <=> Rational(2, 3) # => 1
Rational(4, 3) <=> :foo           # => nil

Rational 클래스는 Comparable 모듈을 포함하는데, 그 모듈의 각 메서드는 비교에 Rational#<=>를 사용해요.

rat == object → true or false

ratobject와 수치상 같으면 true를 반환해요:

Rational(2, 3)  == Rational(2, 3)   #=> true
Rational(5)     == 5                #=> true
Rational(0)     == 0.0              #=> true
Rational('1/3') == 0.33             #=> false
Rational('1/2') == '1/2'            #=> false

abs → rational

rat의 절댓값을 반환해요:

(1/2r).abs    #=> (1/2)
(-1/2r).abs   #=> (1/2)

as_json(*)

Rational#as_jsonRational.json_create 메서드는 Rational 객체를 직렬화/역직렬화하는 데 쓸 수 있어요. Marshal을 참고하세요. Rational#as_jsonself를 직렬화해서 2-요소 해시를 반환해요:

require 'json/add/rational'
x = Rational(2, 3).as_json
# => {"json_class"=>"Rational", "n"=>2, "d"=>3}

JSON.create는 그런 해시를 역직렬화해서 Rational 객체를 반환해요:

Rational.json_create(x)
# => (2/3)

ceil([ndigits]) → integer or rational

rat보다 크거나 같은 가장 작은 수를 ndigits 자리(소수점 아래, 기본 0)의 정밀도로 반환해요. 정밀도가 음수면 최소 ndigits.abs개의 뒤쪽 0을 가진 정수를 반환해요. ndigits가 양수면 유리수를, 그 외에는 정수를 반환해요.

Rational(3).ceil      #=> 3
Rational(2, 3).ceil   #=> 1
Rational(-3, 2).ceil  #=> -1

  #    decimal      -  1  2  3 . 4  5  6
  #                   ^  ^  ^  ^   ^  ^
  #   precision      -3 -2 -1  0  +1 +2

Rational('-123.456').ceil(+1).to_f  #=> -123.4
Rational('-123.456').ceil(-1)       #=> -120

denominator → integer

분모(항상 양수)를 반환해요:

Rational(7).denominator             #=> 1
Rational(7, 1).denominator          #=> 1
Rational(9, -4).denominator         #=> 4
Rational(-2, -10).denominator       #=> 5

fdiv(numeric) → float

나눗셈을 수행하고 Float로 값을 반환해요:

Rational(2, 3).fdiv(1)       #=> 0.6666666666666666
Rational(2, 3).fdiv(0.5)     #=> 1.3333333333333333
Rational(2).fdiv(3)          #=> 0.6666666666666666

floor([ndigits]) → integer or rational

rat보다 작거나 같은 가장 큰 수를 ndigits 자리(기본 0)의 정밀도로 반환해요. 정밀도가 음수면 최소 ndigits.abs개의 뒤쪽 0을 가진 정수를 반환해요. ndigits가 양수면 유리수를, 그 외에는 정수를 반환해요.

Rational(3).floor      #=> 3
Rational(2, 3).floor   #=> 0
Rational(-3, 2).floor  #=> -2

  #    decimal      -  1  2  3 . 4  5  6
  #                   ^  ^  ^  ^   ^  ^
  #   precision      -3 -2 -1  0  +1 +2

Rational('-123.456').floor(+1).to_f  #=> -123.5
Rational('-123.456').floor(-1)       #=> -130

hash()

이 객체의 해시 값을 반환해요.

inspect → string

검사용 문자열로 값을 반환해요:

Rational(2).inspect      #=> "(2/1)"
Rational(-8, 6).inspect  #=> "(-4/3)"
Rational('1/2').inspect  #=> "(1/2)"

magnitude → rational

rat의 절댓값을 반환해요:

(1/2r).abs    #=> (1/2)
(-1/2r).abs   #=> (1/2)

negative? → true or false

rat이 0보다 작으면 true를 반환해요.

numerator → integer

분자를 반환해요:

Rational(7).numerator        #=> 7
Rational(7, 1).numerator     #=> 7
Rational(9, -4).numerator    #=> -9
Rational(-2, -10).numerator  #=> 1

positive? → true or false

rat이 0보다 크면 true를 반환해요.

quo()

quo는 나눗셈을 수행해요. Rational#/과 관련된 메서드예요.

rationalize → self

선택 인자 eps가 주어지면 값의 더 단순한 근사치를 반환하고(rat-|eps| <= result <= rat+|eps|), 주어지지 않으면 self를 반환해요:

r = Rational(5033165, 16777216)
r.rationalize                    #=> (5033165/16777216)
r.rationalize(Rational('0.01'))  #=> (3/10)
r.rationalize(Rational('0.1'))   #=> (1/3)

round([ndigits] [, half: mode]) → integer or rational

ratndigits 자리(기본 0)의 정밀도로 가장 가까운 값으로 반올림해 반환해요. 정밀도가 음수면 최소 ndigits.abs개의 뒤쪽 0을 가진 정수를 반환해요. ndigits가 양수면 유리수를, 그 외에는 정수를 반환해요.

Rational(3).round      #=> 3
Rational(2, 3).round   #=> 1
Rational(-3, 2).round  #=> -2

  #    decimal      -  1  2  3 . 4  5  6
  #                   ^  ^  ^  ^   ^  ^
  #   precision      -3 -2 -1  0  +1 +2

Rational('-123.456').round(+1).to_f  #=> -123.5
Rational('-123.456').round(-1)       #=> -120

선택 인자 half 키워드는 Float#round와 비슷하게 동작해요:

Rational(25, 100).round(1, half: :up)    #=> (3/10)
Rational(25, 100).round(1, half: :down)  #=> (1/5)
Rational(25, 100).round(1, half: :even)  #=> (1/5)
Rational(35, 100).round(1, half: :up)    #=> (2/5)
Rational(35, 100).round(1, half: :down)  #=> (3/10)
Rational(35, 100).round(1, half: :even)  #=> (2/5)
Rational(-25, 100).round(1, half: :up)   #=> (-3/10)
Rational(-25, 100).round(1, half: :down) #=> (-1/5)
Rational(-25, 100).round(1, half: :even) #=> (-1/5)

to_f → float

값을 Float로 반환해요:

Rational(2).to_f      #=> 2.0
Rational(9, 4).to_f   #=> 2.25
Rational(-3, 4).to_f  #=> -0.75
Rational(20, 3).to_f  #=> 6.666666666666667

to_i → integer

절삭(truncate)한 값을 정수로 반환해요. Rational#truncate와 동일해요:

Rational(2, 3).to_i    #=> 0
Rational(3).to_i       #=> 3
Rational(300.6).to_i   #=> 300
Rational(98, 71).to_i  #=> 1
Rational(-31, 2).to_i  #=> -15

to_json(*args)

self를 나타내는 JSON 문자열을 반환해요:

require 'json/add/rational'
puts Rational(2, 3).to_json

출력:

{"json_class":"Rational","n":2,"d":3}

to_r → self

self를 반환해요:

Rational(2).to_r      #=> (2/1)
Rational(-8, 6).to_r  #=> (-4/3)

to_s → string

값을 문자열로 반환해요:

Rational(2).to_s      #=> "2/1"
Rational(-8, 6).to_s  #=> "-4/3"
Rational('1/2').to_s  #=> "1/2"

truncate([ndigits]) → integer or rational

ratndigits 자리(기본 0)의 정밀도로 0 방향으로 절삭해서 반환해요. 정밀도가 음수면 최소 ndigits.abs개의 뒤쪽 0을 가진 정수를 반환해요. ndigits가 양수면 유리수를, 그 외에는 정수를 반환해요.

Rational(3).truncate      #=> 3
Rational(2, 3).truncate   #=> 0
Rational(-3, 2).truncate  #=> -1

  #    decimal      -  1  2  3 . 4  5  6
  #                   ^  ^  ^  ^   ^  ^
  #   precision      -3 -2 -1  0  +1 +2

Rational('-123.456').truncate(+1).to_f  #=> -123.4
Rational('-123.456').truncate(-1)       #=> -120