Int — 임의 크기 정수

Int — 임의 크기 정수

Int 객체는 임의 크기의 정수 를 저장해요. 그리고 Int는 불변(immutable)이에요. 값이 커지면 필요한 만큼 메모리를 써서 정확한 값을 유지하죠.

Int 리터럴은 크게 두 가지 표기법이 있어요. 하나는 우리가 익숙한 십진 표기법, 다른 하나는 기수(radix) 표기법이에요.

123;         # Int in decimal notation
:16<BEEF>;   # Int in radix notation

흔히 쓰는 기수에는 앞에 붙이는 단축 표기법이 준비되어 있어요.

say so :2<11111111> == 0b11111111 == :8<377> == 0o377 == 255 == 0d255 == :16<ff> == 0xff;
# OUTPUT: «True␤»

모든 표기법에서 숫자 사이에 밑줄(_)을 쓸 수 있어요. 시각적 구분자일 뿐 값에는 아무 의미가 없어요.

5_00000;       # five Lakhs
500_000;       # five hundred thousand
0xBEEF_CAFE;   # a strange place
:2<1010_1010>; # 0d170

기수 표기법은 괄호 형태도 지원해요. 소괄호는 문자열을 특정 진법으로 파싱하고, 대괄호는 숫자들을 모아 하나의 정수로 만드는 데 쓰여요.

:16("9F");         # 159
:100[99, 2, 3];    # 990203

이 표기법들은 변수도 사용할 수 있어요.

my $two = "2";
my $ninety-nine = "99";
:16($ninety-nine); # 153
:100[99, $two, 3]; # 990203

출처: Raku Documentation — Int

본문

method new

multi method new(Any:U $type)
multi method new(Any:D \value --> Int:D)
multi method new(int   \value --> Int:D)

첫 번째 형태는 예외를 던져요. 두 번째와 세 번째 형태는 변수에 담긴 실제 정수 값으로부터 새 Int를 만들어요.

method Str

multi method Str(Int:D)
multi method Str(Int:D, :$superscript)
multi method Str(Int:D, :$subscript)

숫자의 문자열 표현을 반환해요.

say 42.Str;                # OUTPUT: «42␤»

CoolInt의 부모 클래스이기 때문에, Int.Str 메서드를 명시적으로 호출할 일은 거의 없어요. 단, 문자열을 위첨자나 아래첨자로 받고 싶을 때는 얘기가 달라지죠.

say 42.Str(:superscript); # OUTPUT: «⁴²␤»
say 42.Str(:subscript);   # OUTPUT: «₄₂␤»

:superscript:subscript 명명 인자는 Rakudo 2023.05 컴파일러 릴리스부터 사용할 수 있어요.

method Capture

method Capture()

X::Cannot::Capture를 던져요.

routine chr

multi        chr(Int:D  --> Str:D)
multi method chr(Int:D: --> Str:D)

정수를 Unicode 코드포인트 번호로 해석해 그에 대응하는 한 글자 문자열을 반환해요.

예시:

65.chr;  # returns "A"
196.chr; # returns "Ä"

routine expmod

multi        expmod(      $x,     $y,     $mod --> Int:D)
multi        expmod(Int:D $x, Int $y, Int $mod --> Int:D)
multi method expmod(Int:D:    Int $y, Int $mod --> Int:D)

주어진 Int$mod 나머지 범위(modulus) 안에서 $y 제곱한 값, 즉 ($x ** $y) mod $mod 의 결과를 반환해요. 서브루틴 형태는 Int가 아닌 인자도 받으며, Int로 강제 변환돼요.

say expmod(4, 2, 5);    # OUTPUT: «1␤»
say 7.expmod(2, 5);     # OUTPUT: «4␤»

$y 인자는 음수일 수도 있어요. 이 경우 결과는 ($x ** $y) mod $mod와 동일해요.

say 7.expmod(-2, 5);     # OUTPUT: «4␤»

method polymod

method polymod(Int:D: +@mods)

@mods에 들어있는 나눗셈수(divisor)들에 대응하는 나머지 결과들의 시퀀스를, 주어진 순서대로 반환해요. 가장 좋은 효과를 보려면 나눗셈수를 가장 작은 "단위"부터 큰 순서로 주는 게 좋아요(예: 1분은 60초, 1시간은 60분). 결과도 같은 방식으로 가장 작은 것부터 큰 순서로 나와요(5초, 4분). 마지막으로 남는 0이 아닌 값이 마지막 나머지예요.

say 120.polymod(10);    # OUTPUT: «(0 12)␤»
say 120.polymod(10,10); # OUTPUT: «(0 2 1)␤»

첫 번째 경우, 120을 10으로 나눈 나머지는 12이고 그게 마지막 요소예요. 두 번째 경우, 120을 10으로 div하면 12가 되고, 그 12를 다시 10으로 나눈 나머지는 2, 또 12 div 10의 정수 나눗셈 결과가 마지막 나머지가 되죠. 나머지의 개수는 항상 주어진 나눗셈수보다 하나 더 많아요. 나눗셈수를 lazy 리스트로 주면 나머지가 0이 되거나 나눗셈수 목록이 다 소진될 때까지 계속돼요.

my $seconds = 1 * 60*60*24 # days
            + 3 * 60*60    # hours
            + 4 * 60       # minutes
            + 5;           # seconds

say $seconds.polymod(60, 60);                # OUTPUT: «(5 4 27)␤»
say $seconds.polymod(60, 60, 24);            # OUTPUT: «(5 4 3 1)␤»

say 120.polymod:      1, 10, 10², 10³, 10⁴;  # OUTPUT: «(0 0 12 0 0 0)␤»
say 120.polymod: lazy 1, 10, 10², 10³, 10⁴;  # OUTPUT: «(0 0 12)␤»
say 120.polymod:      1, 10, 10² … ∞;        # OUTPUT: «(0 0 12)␤»
my @digits-in-base37 = 9123607.polymod(37 xx *); # Base conversion
say @digits-in-base37.reverse                    # OUTPUT: «[4 32 4 15 36]␤»

Int에 대해 호출할 때 모든 나눗셈수는 Int여야 해요.

say 120.polymod(⅓);                            # ERROR

Int용 비-lazy polymod이 실제로 어떻게 동작하는지 이 코드로 살펴볼 수 있어요.

my $seconds = 2 * 60*60*24 # days
            + 3 * 60*60    # hours
            + 4 * 60       # minutes
            + 5;           # seconds

my @pieces;
for 60, 60, 24 -> $divisor {
    @pieces.push: $seconds mod $divisor;
    $seconds div= $divisor
}
@pieces.push: $seconds;

say @pieces; # OUTPUT: «[5 4 3 2]␤»

더 자세한 설명은 이 블로그 글을 참고하세요.

polymod에는 lazy 리스트도 쓸 수 있는데, 유한한 리스트여야 해요.

my $some-numbers = lazy gather { take 3*$_ for 1..3 };
say 600.polymod( $some-numbers ); # OUTPUT: «(0 2 6 3)␤»

routine is-prime

multi        is-prime (Int:D $number --> Bool:D)
multi method is-prime (Int:D: --> Bool:D)

Int가 소수임이 알려져 있거나, 확률적 Miller-Rabin 테스트에 기반해 소수일 가능성이 높으면 True를 반환해요.

Int가 소수가 아님을 알고 있으면 False를 반환해요.

say 2.is-prime;         # OUTPUT: «True␤»
say is-prime(9);        # OUTPUT: «False␤»

routine lsb

multi method lsb(Int:D:)
multi        lsb(Int:D)

"Least Significant Bit"(최하위 비트)의 줄임말이에요. 숫자가 0이면 Nil을 반환해요. 그렇지 않으면 숫자의 이진 표현에서 가장 오른쪽에 있는 1 의 오른쪽에서부터 0 기반 인덱스를 반환해요.

say 0b01011.lsb;        # OUTPUT: «0␤»
say 0b01010.lsb;        # OUTPUT: «1␤»
say 0b10100.lsb;        # OUTPUT: «2␤»
say 0b01000.lsb;        # OUTPUT: «3␤»
say 0b10000.lsb;        # OUTPUT: «4␤»

routine msb

multi method msb(Int:D:)
multi        msb(Int:D)

"Most Significant Bit"(최상위 비트)의 줄임말이에요. 숫자가 0이면 Nil을 반환해요. 그렇지 않으면 숫자의 이진 표현에서 가장 왼쪽에 있는 1 의 오른쪽에서부터 0 기반 인덱스를 반환해요.

say 0b00001.msb;        # OUTPUT: «0␤»
say 0b00011.msb;        # OUTPUT: «1␤»
say 0b00101.msb;        # OUTPUT: «2␤»
say 0b01010.msb;        # OUTPUT: «3␤»
say 0b10011.msb;        # OUTPUT: «4␤»

routine unival

multi        unival(Int:D  --> Numeric)
multi method unival(Int:D: --> Numeric)

주어진 정수 번호를 가진 Unicode 코드포인트가 나타내는 숫자 를 반환해요. 숫자를 나타내지 않으면 NaN을 반환해요.

say ord("¾").unival;    # OUTPUT: «0.75␤»
say 190.unival;         # OUTPUT: «0.75␤»
say unival(65);         # OUTPUT: «NaN␤»

method Range

지원하는 값의 범위를 나타내는 Range 객체를 반환해요.

method Bridge

method Bridge(Int:D: --> Num:D)

정수를 Num으로 변환한 값을 반환해요.

Operators

infix div

multi infix:<div>(Int:D, Int:D --> Int:D)

정수 나눗셈을 수행하되 내림(round down) 해요.