Поменять i бит числа на 1 или 0

Всем привет

Стоит задача Поменять i-й бит числа в 1 или 0. Я сделал так, но меня смущает что много приведений типов и кода в принципе много для такой задачи. Как еще это можно сделать?

package main

import (
    "fmt"
    "log"
    "strconv"
)

func IntToBits(num int) string {
    return strconv.FormatInt(int64(num), 2)
}

func bitsToInt(s string) int64 {
    newVal, err := strconv.ParseInt(s, 2, 64)
    if err != nil {
        log.Fatal(err)
    }
    return newVal
}

func changeOneBit(num, position, newBit int) int64 {
    if position > 0 && num == 0 {
        return int64(num)
    }

    if newBit > 1 || newBit < 0 {
        log.Println("Новый бит может быть только 1 или 0")
        return int64(num)
    }

    bits := []byte(IntToBits(num))
    fmt.Printf("Было \t %s(%v)\n", string(bits), num)

    if position >= len(bits) {
        log.Printf("В числе %v нет %v разрядов. Разярядов в числе %v только %v\n", num, position, num, len(bits))
        return int64(num)
    }

    newB := []byte(IntToBits(newBit))
    bits[position] = newB[0]
    newVal := bitsToInt(string(bits))
    fmt.Printf("Стало \t %s(%v)\n", string(bits), newVal)
    return newVal
}
func main(){
    log.Println(changeOneBit(12, 3, 1)) //8
}

Ответы (1 шт):

Автор решения: MBo

Для того, чтобы поменять только один k-й бит, нужно создать маску - число с таким набором битов, что при выполнении соответствующей побитовой операции изменится только нужный бит, а остальные останутся неизменными.

Для операции установки бита c помощью побитового OR это маска вида 0b00001000, а для операции сброса бита c помощью побитового AND маска вида 0b11110111

Первую легко получить, сдвинув единицу на k позиций.

А вторую - побитово инвертировав первую.

Пример: нужно установить третий бит

01010110
     ^ вот этот
mask=00000001 << 3  = 00001000

01010110   or
00001000
--------
01011110

Операция or c нулевыми битами маски не меняет соответствующие биты числа.

Теперь в результате сбросим это же бит

mask = not(00000001 << 3) = not(00001000) = 11110111

01011110  and
11110111
--------
01010110

Операция and c единичными битами маски не меняет соответствующие биты числа.

В обоих случаях все биты, кроме третьего, остались прежними

→ Ссылка