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
본문
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»
Cool이 Int의 부모 클래스이기 때문에, 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) 해요.