본문 바로가기
공부/코틀린쿡북

2.6 숫자를 거듭제곱하기, 2.7 비트 시프트 연산자 사용하기

by 띵커베르 2024. 4. 21.
728x90

숫자를 거듭제곱하기

 

코틀린에는 자바처럼 내장 거듭제곱 연산자가 없다.

정수의 값을 거듭제곱하려면 -> Double 또는 Float 형으로 치환 후 pow 연산자를 호출후에 다시 원래의 타입으로 되돌려줘야 한다

 

이는 infix 연산자로 정의하는 방법이 있을 수 있다.

infix fun Int.`**`(x: Int) = toDouble().pow(x).toInt()
infix fun Long.`**`(x: Int) = toDouble().pow(x).toLong()
infix fun Float.`**`(x: Int) = this.toDouble().pow(x.toDouble()).toFloat()
infix fun Double.`**`(x: Int) = pow(x.toDouble()).toInt()

// Float 과 Double 에 존재하는 함수와 비슷한 패턴
fun Int.pow(x: Int): Int = `**`(x)
fun Long.pow(x: Int): Long = `**`(x)


@Test
fun `레시피 2_6 숫자를 거듭제곱하기_2`() {
    val number: Int = 2
    val result = number * number
    println(result)
    assertThat(result).isEqualTo(4)

    val pow1 = number `**` 2
    val pow2 = number `**` 3

    assertThat(pow1).isEqualTo(4)
    assertThat(pow2).isEqualTo(8)

    val pow3 = number.pow(2)
    val pow4 = number.pow(3)
    assertThat(pow3).isEqualTo(4)
    assertThat(pow4).isEqualTo(8)
}

 

  • closeTo - 부동소수점 비교할 때 사용되는 함수. 특히 double 타입의 값들은 컴퓨터에서 정밀도의 한계로 인해 정확한 계산이 어렵기 때문에, 정확한 일치 비교를 하기 어렵다.
    이 때문에 실제 값과 기대 값 사이의 약간츼 오차를 허용하는 비교 방법
@Test
fun closeTo_test() {
    val a = 2.0 + 1.0
    assertThat(a).isCloseTo(2.9, Offset.offset(0.2))

    val b = 1.0 / 3.0
    assertThat(b).isCloseTo(0.333, Offset.offset(0.001))
}

 

 

* 어떤 수를 2제곱하고싶다면 shl 과 shr 함수를 사용하는 것이 가장 이상적이다. (아래 비트연산)


 

비트 시프트 연산자 사용하기

 

코틀린에서는 비트 시프트를 위한 shr, shl, ushr 같은 비트 중위 연산자(infix)가 있다.

  • shl: 부호 있는 왼쪽 시프트
  • shr: 부호 있는 오른쪽 시프트
  • ushr: 부호 없는 오른쪽 시프트
@Test
fun `비트 연산자 shl 사용`() {
    // 1 = 0000_0001
    val shiftLeft1 = 1 shl 1 // 00000_0010
    val shiftLest2 = 1 shl 2 // 00000_0100
    val shiftLest3 = 1 shl 3 // 00000_1000
    val shiftLest4 = 1 shl 4 // 00001_0000
    val shiftLest5 = 1 shl 5 // 00010_0000
    val shiftLest6 = 1 shl 6 // 00100_0000
    val shiftLest7 = 1 shl 7 // 01000_0000

    assertThat(shiftLeft1).isEqualTo(2)
    assertThat(shiftLest2).isEqualTo(4)
    assertThat(shiftLest3).isEqualTo(8)
    assertThat(shiftLest4).isEqualTo(16)
    assertThat(shiftLest5).isEqualTo(32)
    assertThat(shiftLest6).isEqualTo(64)
    assertThat(shiftLest7).isEqualTo(128)
}

@Test
fun `비트 연산자 shr 사용`() {
    // 235 = 1110_1011
    val shiftRight1 = 235 shr 1 //0111_0101
    val shiftRight2 = 235 shr 2 //0011_1010
    val shiftRight3 = 235 shr 3 //0001_1101
    val shiftRight4 = 235 shr 4 //0000_1110
    val shiftRight5 = 235 shr 5 //0000_0111
    val shiftRight6 = 235 shr 6 //0000_0011
    val shiftRight7 = 235 shr 7 //0000_0001

    assertThat(shiftRight1).isEqualTo(117)
    assertThat(shiftRight2).isEqualTo(58)
    assertThat(shiftRight3).isEqualTo(29)
    assertThat(shiftRight4).isEqualTo(14)
    assertThat(shiftRight5).isEqualTo(7)
    assertThat(shiftRight6).isEqualTo(3)
    assertThat(shiftRight7).isEqualTo(1)

    println(117 shl 1)
}

@Test
fun `비트 연산자 usr 과 ushr 비교`() {
    val n1 = 5
    val n2 = -5
    println(n1.toString(2)) // 101
    println(n2.toString(2)) // -101

    val shiftRight1 = n1 shr 1
    val shiftRight2 = n1 ushr 1

    println(shiftRight1.toString(2)) // 10
    println(shiftRight2.toString(2)) // 10

    val shiftRight3 = n2 shr 1
    val shiftRight4 = n2 ushr 1

    println(shiftRight3.toString(2)) // -10
    println(shiftRight4.toString(2)) // 1111111111111111111111111111101
}

 

728x90

댓글