Enumerator
- Enumerator はオブジェクトの要素を列挙するためのクラス
- Enumerable をインクルードしているので、Enumerable のメソッドを利用できる
- Enumerator の生成にはメソッド Object#to_enum (または Object#enum_for) を使う
object.to_enum(method, *args) => Enumerator
- method は object から要素を取得するためのメソッドをシンボルで指定する
- args には method に渡す引数を指定する
- method を省略すると each() が使用される
- Ruby 2.3 以降ではブロックを省略すると Enumerator を返すメソッドがたくさん用意されている
- 要素を返すメソッドは next(), next_values(), peek(), peek_values() がある
- next 系はイテレータを次の要素に進めるが、peek 系は進めない
- values 系は要素を配列に格納して返す
- メソッド rewind() は最初の状態に巻き戻す
- メソッド with_index() はインデックス付きの each()
with_index(offset=0) {|(*args), idx| ... } => object
- メソッド each_with_index() と違って offset を指定できる
irb> class Foo
irb> def each
irb> yield 1
irb> yield 2
irb> yield 3
irb> end
irb> end
=> :each
irb> a = Foo.new
=> #<Foo: ... >
irb> a.map {|x| x * x}
(irb):?:in `<main>': undefined method `map' for #<Foo:...> (NoMethodError)
・・・省略・・・
irb> e = a.to_enum
=> #<Enumerator: ...>
irb> e.map {|x| x * x}
=> [1, 4, 9]
irb> e.next
=> 1
irb> e.next
=> 2
irb> e.next
=> 3
irb> e.next
(irb):?:in `next': iteration reached an end (StopIteration)
・・・省略・・・
irb> e.rewind
=> #<Enumerator: ...>
irb> e.peek
=> 1
irb> e.peek
=> 1
irb> e.peek_values
=> [1]
irb> e.next_values
=> [1]
irb> e.next_values
=> [2]
irb> [1,2,3,4,5].to_enum.with_index{|k, i| print i, " ", k, "\n"}
0 1
1 2
2 3
3 4
4 5
=> [1, 2, 3, 4, 5]
irb> [1,2,3,4,5].to_enum.with_index(1){|k, i| print i, " ", k, "\n"}
1 1
2 2
3 3
4 4
5 5
=> [1, 2, 3, 4, 5]
irb> [1,2,3,4,5].each_with_index{|k, i| print i, " ", k, "\n"}
0 1
1 2
2 3
3 4
4 5
=> [1, 2, 3, 4, 5]
irb> ints = Enumerator.new(Float::INFINITY) {|y|
irb> n = 1
irb> loop {
irb> y << n
irb> n += 1
irb> }
irb> }
=> #<Enumerator: ...>
irb> ints.next
=> 1
irb> ints.next
=> 2
irb> ints.next
=> 3
irb> ints.next
=> 4
irb> ints.next
=> 5
irb> ints.rewind
=> #<Enumerator: ...>
irb> ints.next
=> 1
irb> ints.next
=> 2
irb> ints.next
=> 3
irb> ints.size
=> Infinity
- ints は無限の整数列 (1, 2, 3, ...) を生成する
- 無限リストの場合、map(), select(), drop() など配列を返すメソッドは使用できない (無限の配列を返そうとするため)
- 無限リストを取り扱うにはメソッド Enumerable#lazy で Enumerator を Enumerator::Lazy に変換する
- 本稿では Enumerator::Lazy のオブジェクトを「遅延リスト」と呼ぶことにする
●参考 URL
Enumerator::Lazy
- Enumerator::Lazy は遅延リストを表すクラス
- map(), select(), drop() などのメソッドが遅延評価版に切り替わる
- 遅延リストはメソッド Enumerable#lazy で生成する
- 遅延リストから値を取り出すにはメソッド force() か first() を使う
- first() は先頭要素を取り出す
- first(n) は先頭から n 個の要素を取り出して配列に格納して返す
irb> intslazy = ints.lazy
=> #<Enumerator::Lazy: ...>
irb> intslazy.next
=> 1
irb> intslazy.next
=> 2
irb> intslazy.next
=> 3
irb> ints.lazy.drop(100)
=> #<Enumerator::Lazy: ...>
irb> ints.lazy.drop(100).first
=> 101
irb> ints.lazy.drop(100).first(10)
=> [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
irb> ints.lazy.map {|x| x * 2}
=> #<Enumerator::Lazy: ...>
irb> ints.lazy.map {|x| x * 2}.take(10).force
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
irb> ints.lazy.map {|x| x * 2}.first(10)
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- 無限の整数列は (1..Float::INFINITY).lazy でも生成できる
- Enumerator や Enumerator::Lazy は immutable ではない (メソッド next() は状態を変化させている)
- また、実行結果もキャッシュしていない
- 一般に、関数型言語の「遅延ストリーム」は immutable なので、それとは使い勝手が異なることに注意
●簡単な例題
リスト : 無限数列の生成
def iterate(a, &func)
Enumerator.new(Float::INFINITY) {|y|
n = a
loop {
y << n
n = func.call(n)
}
}.lazy
end
def tabulate(a = 0, &func)
Enumerator.new(Float::INFINITY) {|y|
n = a
loop {
y << func.call(n)
n += 1
}
}.lazy
end
irb> iterate(1, &:itself).first(10)
=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
irb> iterate(2, &:itself).first(10)
=> [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
irb> iterate(1){|x| x + 1}.first(10)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb> iterate(1){|x| x + 2}.first(10)
=> [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
irb> iterate([0, 1]){|x, y| [y, y + x]}.first(10)
=> [[0, 1], [1, 1], [1, 2], [2, 3], [3, 5], [5, 8], [8, 13], [13, 21], [21, 34], [34, 55]]
irb> iterate([0, 1]){|x, y| [y, y + x]}.map{|x| x[0]}.first(10) # フィボナッチ数
=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
irb> iterate([2, 1]){|x, y| [y, y + x]}.map{|x| x[0]}.first(10) # リュカ数
=> [2, 1, 3, 4, 7, 11, 18, 29, 47, 76]
irb> iterate([0, 0, 1]){|x, y, z| [y, z, z + y + x]}.map{|x| x[0]}.first(20) # トリボナッチ数
=> [0, 0, 1, 1, 2, 4, 7, 13, 24, 44, 81, 149, 274, 504, 927, 1705, 3136, 5768, 10609, 19513]
irb> tabulate(&:itself).first(10)
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
irb> tabulate(10, &:itself).first(10)
=> [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
irb> tabulate(1){|x| x * (x + 1) / 2}.first(10) # 三角数
=> [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
irb> tabulate(1){|x| x * x}.first(10) # 四角数
=> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
irb> tabulate(1){|x| x * (3 * x - 1) / 2}.first(10) # 五角数
=> [1, 5, 12, 22, 35, 51, 70, 92, 117, 145]
irb> def to_fizzbuzz(n)
irb> if n % 15 == 0
irb> "FizzBuzz"
irb> elsif n % 3 == 0
irb> "Fizz"
irb> elsif n % 5 == 0
irb> "Buzz"
irb> else
irb> n.to_s
irb> end
irb> end
=> :to_fizzbuzz
irb> tabulate(1){|x| to_fizzbuzz(x)}.first(100)
=> ["1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz",
"13", "14", "FizzBuzz", "16", "17", "Fizz", "19", "Buzz", "Fizz", "22", "23", "Fizz",
"Buzz", "26", "Fizz", "28", "29", "FizzBuzz", "31", "32", "Fizz", "34", "Buzz",
"Fizz", "37", "38", "Fizz", "Buzz", "41", "Fizz", "43", "44", "FizzBuzz", "46", "47",
"Fizz", "49", "Buzz", "Fizz", "52", "53", "Fizz", "Buzz", "56", "Fizz", "58", "59",
"FizzBuzz", "61", "62", "Fizz", "64", "Buzz", "Fizz", "67", "68", "Fizz", "Buzz",
"71", "Fizz", "73", "74", "FizzBuzz", "76", "77", "Fizz", "79", "Buzz", "Fizz", "82",
"83", "Fizz", "Buzz", "86", "Fizz", "88", "89", "FizzBuzz", "91", "92", "Fizz", "94",
"Buzz", "Fizz", "97", "98", "Fizz", "Buzz"]
irb> def newton(n)
irb> iterate(n) {|x| (x + n / x) / 2.0}
irb> end
=> :newton
irb> newton(2).first(10)
=> [2, 1.5, 1.4166666666666665, 1.4142156862745097, 1.4142135623746899,
1.414213562373095, 1.414213562373095, 1.414213562373095, 1.414213562373095,
1.414213562373095]
irb> newton(3).first(10)
=> [3, 2.0, 1.75, 1.7321428571428572, 1.7320508100147274, 1.7320508075688772,
1.7320508075688772, 1.7320508075688772, 1.7320508075688772, 1.7320508075688772]
リスト : 素数列 (myprime.rb)
class Myprime
@@primes = [2, 3, 5] # 求めた素数を格納
# 次の素数を求める
def Myprime.next_prime(n)
while true
for p in @@primes
return n if p * p > n
break if n % p == 0
end
n += 2
end
end
# 素数列の生成
def Myprime.make
Enumerator.new(Float::INFINITY) {|y|
n = 0
while true
if n == @@primes.size
@@primes.push Myprime.next_prime(@@primes[-1] + 2)
end
y << @@primes[n]
n += 1
end
}.lazy
end
end
irb> load "myprime.rb"
=> true
irb> ps = Myprime.make
=> #<Enumerator::Lazy: ...>
irb> ps.first(25)
=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
79, 83, 89, 97]
irb> ps.first(100)
=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167,
173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263,
269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367,
373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
467, 479, 487, 491, 499, 503, 509, 521, 523, 541]
irb> ps.drop(1000).first(10)
=> [7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017]
●参考 URL
Fiber
- 概要
- Ruby の Fiber はコルーチン (co-routine) のこと
- 関数 (サブルーチン, sub-routine) は call してから return するまで途中で処理を中断することはできない
- コルーチンは途中で処理を中断し、そこから実行を再開することができる
- Ruby のコルーチンは「セミコルーチン (semi-coroutine)」が基本
- セミコルーチンには親子関係があり、コルーチン A からコルーチン B を呼び出した場合、A が親で B が子になる
- 本稿では Fiber をコルーチンと記述する
- コルーチン は Fiber.new { ... } で生成する
- コルーチンを実行 (または再開) するにはメソッド resume() を使う
- rensume() を呼び出したほうが親、呼び出されたほうが子になる
- 子コルーチンの中でクラスメソッド Fiber.yield() を実行すると、そこでプログラムの実行を中断して親コルーチンに戻る
- yield() の引数が親コルーチンで呼び出した resume() の返り値になる
- resume() に引数を渡して実行を再開すると、それが Fiber.yield() の返り値となる
irb(main)> co = Fiber.new {
irb(main)> for x in 1 .. 4
irb(main)> Fiber.yield x
irb(main)> end
irb(main)> 5
irb(main)> }
=> #<Fiber:0x000055e61811b3f0 (irb):? (created)>
irb> co.resume
=> 1
irb> co.resume
=> 2
irb> co.resume
=> 3
irb> co.resume
=> 4
irb> co.resume
=> 5
irb> co.resume
(irb):?:in `resume': attempt to resume a terminated fiber (FiberError)
・・・省略・・・
- resume() が返す値は Fiber.yield() だけではなくブロックの実行結果も返す
- 終了したコルーチンに resume() を適用するとエラーになる
●簡単な例題
リスト : 複数のコルーチン
def print_code(code)
loop {
print code
Fiber.yield true
}
end
def test_a(n)
xs = ["h", "e", "y", "!", " "].map {|x| Fiber.new {print_code(x)}}
n.times {
xs.each {|co| co.resume}
}
end
irb> test_a(5)
hey! hey! hey! hey! hey! => 5
irb> test_a(10)
hey! hey! hey! hey! hey! hey! hey! hey! hey! hey! => 10
リスト : 順列の生成
def perm_sub(xs, n)
if xs.size == n
Fiber.yield []
else
co = Fiber.new { perm_sub(xs, n + 1) }
while ys = co.resume
for x in xs
if not ys.member? x
Fiber.yield(ys + [x])
end
end
end
end
end
def permutation(xs)
Fiber.new { perm_sub(xs, 0) }
end
irb> co = permutation([1,2,3])
=> #<Fiber:0x0000563306296ac8 sample_fiber.rb:? (created)>
irb> while xs = co.resume
irb> print xs, "\n"
irb> end
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
=> nil
リスト : エラトステネスの篩
# n から始まる整数列
def integers(n)
Fiber.new {
loop {
Fiber.yield n
n += 1
}
}
end
# フィルター
def filter(src)
Fiber.new {
while m = src.resume
Fiber.yield(m) if yield(m)
end
}
end
def sieve(x)
nums = integers(2)
x.times {
n = nums.resume
print n, " "
nums = filter(nums) {|x| x % n != 0}
}
end
irb> sieve 25
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 => 25
irb> sieve 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107
109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227
229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349
353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467
479 487 491 499 503 509 521 523 541 => 100
Rational
- Rational は有理数 (分数) を表すクラス
- require は必要ない
- 有理数の生成は Kernel#Rational を使う
- Rational.new はエラー
Rational(分子, [分母])
- 分母を省略すると 1 になる
- 分子と分母は数または文字列
- 実数 (Float) の場合、分数には正確に変換できないことがある
- 文字列の場合、分数の形式 "1/3" や実数の形式でも OK
irb> Rational(1, 3)
=> (1/3)
irb> Rational("1/3")
=> (1/3)
irb> Rational(0.1)
=> (3602879701896397/36028797018963968)
irb> Rational("0.1")
=> (1/10)
irb> Rational(1e-3)
=> (1152921504606847/1152921504606846976)
irb> Rational("1e-3")
=> (1/1000)
- numerator, 分子を返す
- denominator, 分母を返す
- 算術演算子 (+, -, *, /, %, **)
- 有理数と有理数、有理数と整数の演算は有理数になる
- 除算の結果を実数で得たいときは fdiv を使う
- 有理数と実数の演算結果は実数になる
- 比較演算子 (==, !=, <=>, < > <=, >=)
- 数に適用できるメソッドであれば、たいていは有理数にも適用可
- zero?, positive?, negative?, ceil, floor, round, truncate, etc...
irb> a = Rational(1, 2)
=> (1/2)
irb> b = Rational(1, 3)
=> (1/3)
irb> a + b
=> (5/6)
irb> a - b
=> (1/6)
irb> b - a
=> (-1/6)
irb> a * b
=> (1/6)
irb> a / b
=> (3/2)
irb> b / a
=> (2/3)
irb> a ** 2
=> (1/4)
irb> a ** 10
=> (1/1024)
irb> 2 ** a
=> 1.4142135623730951
irb> 8 ** b
=> 2.0
irb> a < b
=> false
irb> a > b
=> true
irb> a == b
=> false
irb> a != b
=> true
irb> a == a
=> true
irb> a <=> b
=> 1
irb> b <=> a
=> -1
irb> b <=> b
=> 0
Complex
- Complex は複素数を表すクラス
- require は必要ない
- 数学では複素数 z を x + yi と表記する
- x を実部、y を虚部、i を虚数単位という
- 虚数単位は 2 乗すると -1 になる数
- 実部と虚部の 2 つの数値を格納するデータ構造を用意すれば、プログラミング言語でも複素数を表すことができる
- 複素数の生成は Kernel#Complex, Complex.polor, Complex.rect, Numeric#to_c, String#to_c のいずれかを使う
- Complex.new はエラー
Complex(実部, 虚部 = 0)
Complex.rect(実部, 虚部 = 0)
Complex.rectangular(実部, 虚部 = 0)
- 虚部を省略すると 0 になる
- 実部と虚部は数または文字列
- 文字列の場合、複素数の形式 "1+2i" も OK
実部は real, 虚部は imag で取得できる
複素共役 (虚部の符号を反転した数) は conjugate または conj で求める
虚数単位は Complex::I
irb> Complex(1, 2)
=> (1+2i)
irb> Complex.rect(3, 4)
=> (3+4i)
irb> Complex(1)
=> (1+0i)
irb> Complex("1+2i")
=> (1+2i)
irb> Complex("1.0+2.0i")
=> (1.0+2.0i)
irb> Complex::I
=> (0+1i)
irb> a = Complex(1.2, 3.4)
=> (1.2+3.4i)
irb> a.real
=> 1.2
irb> a.imag
=> 3.4
irb> a.conjugate
=> (1.2-3.4i)
irb> a.conj
=> (1.2-3.4i)
- 複素数は極形式 z = |z|(cos θ + i sin θ) で表すことができる
- このとき、|z| を絶対値、θ を偏角という
- 絶対値はメソッド abs, magnitude で求めることができる
- 偏角は複素平面において正の実軸とベクトル (x, y) との角度 θ を表す
- 偏角 θ を求めるメソッドには arg, angle, phase がある
- 返り値 θ は -pi <= θ <= pi (pi : 円周率)
- Complex.polar() は絶対値と偏角から複素数を生成する
Complex.polar(絶対値, 偏角)
irb> b = Complex(1, 1)
=> (1+1i)
irb> b.abs
=> 1.4142135623730951
irb> b.arg
=> 0.7853981633974483
irb> Complex.polar(b.abs, b.arg)
=> (1.0000000000000002+1.0i)
irb> Complex(1.0, 0.0).arg
=> 0.0
irb> Complex(1.0, 1.0).arg
=> 0.7853981633974483
irb> Complex(0.0, 1.0).arg
=> 1.5707963267948966
irb> Complex(-1.0, 1.0).arg
=> 2.356194490192345
irb> Complex(-1.0, 0.0).arg
=> 3.141592653589793
irb> Complex(1.0, -1.0).arg
=> -0.7853981633974483
irb> Complex(0.0, -1.0).arg
=> -1.5707963267948966
irb> Complex(-1.0, -1.0).arg
=> -2.356194490192345
irb> Complex(-1.0, -0.0).arg
=> -3.141592653589793
- -1.0+0.0j の偏角 θ は pi になり、-1.0-0.0j の偏角は -pi になる
- -0.0 は「負のゼロ」を表す
- ゼロと負のゼロを区別しないプログラミング言語もある
- その場合は、偏角 θ の範囲を -pi < θ <= pi に制限して、-1.0 + 0.0j (== -1.0 - 0.0j) の偏角を pi とする
- Ruby の場合、負のゼロは Float のメソッド arg, angle, phase で判定できる
- 符号が正ならば 0 を、負ならば Math::PI を返す
irb> 1.0.arg
=> 0
irb> -1.0.arg
=> 3.141592653589793
irb> 0.0.arg
=> 0
irb> -0.0.arg
=> 3.141592653589793
- 複素数の四則演算
- (a + bi) + (c + di) = (a + c) + i(b + d)
- (a + bi) - (c + di) = (a - c) + i(b - d)
- (a + bi) * (c + di) = (ac - bd) + i(bc + ad)
- (a + bi) / (c + di) = ((ac + bd) + i(bc - ad)) / (c2 + d2)
- 算術演算子 (+, -, *, /, **)
- Complex 以外の数との演算も可能、返り値は Complex になる
- 比較演算子 (==, !=, <=>)
- 複素数で大小の比較はできない、等値演算子は適用可
- 演算子 <=> は両辺の虚部が 0 のときのみ適用可
irb> a = Complex(1.0, 2.0)
=> (1.0+2.0i)
irb> b = Complex(3.0, 4.0)
=> (3.0+4.0i)
irb> a + b
=> (4.0+6.0i)
irb> a - b
=> (-2.0-2.0i)
irb> a * b
=> (-5.0+10.0i)
irb> a / b
=> (0.44+0.08i)
irb> a ** 2
=> (-3.0+4.0i)
irb> a * a
=> (-3.0+4.0i)
irb> a ** 3
=> (-11.0-2.0i)
irb> a * a * a
=> (-11.0-2.0i)
irb> a == a
=> true
irb> a == b
=> false
irb> a != b
=> true
- 実部と虚部の値は無限大 (Float::INFINITY) や非数 (FLOAT::NAN) になることもある
- finite? は実部と虚部が有限の値であれば真を返す
- infinite? は実部と虚部がどちらも無限大でなければ nil を、そうでなければ 1 を返す
- 実数の場合、無限大は Float のメソッド finite? や infinite? で、非数の判定は nan? で行うことができる
irb> Float::INFINITY
=> Infinity
irb> Float::NAN
=> NaN
irb> a = Complex(1e300, 1e300)
=> (1.0e+300+1.0e+300i)
irb> a.finite?
=> true
irb> a.infinite?
=> nil
irb> b = a * a
=> (NaN+Infinity*i)
irb> b.finite?
=> false
irb> b.infinite?
=> 1
irb> b.real.nan?
=> true
irb> b.real.nan?
=> true
irb> b.imag.infinite?
=> 1
整数のビット演算
- 論理演算子
- x & y
x と y の論理積を求める
- x | y
x と y の論理和を求める
- x ^ y
x と y の排他的論理和を求める
- ~x
x の否定 (ビットの反転)
- シフト演算子
- x << n
x を n ビット左シフトする
- x >> n
x を n ビット右シフトする
- これらの演算子はC言語のそれと同じ
- [] 演算子
- x[n]
n 番目のビットがオンならば 1 を返す, (x >> n) & 1 と同じ
- x[n, k]
n 番目のビットから上位 k 個のビットを返す, (x >> n) & ((1 << k) - 1) と同じ
- x[i..j]
(x >> i) & ((1 << (j - i + 1)) - 1) と同じ
- x[i...j]
(x >> i) & ((1 << (j - i)) - 1) と同じ
- allbits?(mask)
self & mask == mask と同じ
- anybits?(mask)
self & mask != 0 と同じ
- bit_length
整数を表すのに必要なビット数 (符号ビットを除く最上位のビット位置 + 1) を返す。
irb> printf "%04b\n", 0b0101 & 0b0011
0001
=> nil
irb> printf "%04b\n", 0b0101 | 0b0011
0111
=> nil
irb> printf "%04b\n", 0b0101 ^ 0b0011
0110
=> nil
irb> ~1
=> -2
irb> ~0
=> -1
irb> 1 << 8
=> 256
irb> 1 << 16
=> 65536
irb> 256 >> 8
=> 1
irb> 65536 >> 8
=> 256
irb> -256 >> 8
=> -1
irb> for i in 0..5
irb> print 0b010101[i], " "
irb> end
1 0 1 0 1 0 => 0..5
irb> printf "%b\n", 0b11001101[3, 1]
1
=> nil
irb> printf "%b\n", 0b11001101[3...7]
1001
=> nil
irb> printf "%b\n", 0b11001101[3..7]
11001
=> nil
irb> 0b11001101.allbits?(0b1101)
=> true
irb> 0b11001100.allbits?(0b1101)
=> false
irb> 0b11001101.anybits?(0b1100)
=> true
irb> 0b11000000.anybits?(0b1100)
=> false
irb> 0x100.bit_length
=> 9
irb> 0x800.bit_length
=> 12
irb> 0xffff.bit_length
=> 16
irb> 0.bit_length
=> 0
初版 2017 年 1 月 22 日
改訂 2023 年 1 月 28 日