如何翻转Erlang位串中的单个特定位?
如何在Erlang中翻转位串的单个特定位?
看起来你已经为位串操作写了不错的基础模块啦!要实现翻转单个特定位的功能其实很简单——核心就是把目标位的0和1互相取反。我来帮你完善这个模块:
首先先确认一下你现有的bitutils模块代码:
-module (bitutils). -export ([get_bits/1, get_bit/2, set_bit/2]). get_bits(B) -> << <<X>> || <<X:1>> <= B >>. get_bit(Bin, N) -> << _:N/bitstring, Bit:1, _/bitstring >> = Bin, Bit. set_bit(Bin, N) -> << A:N, _:1, B/bitstring >> = Bin, << A:N, 1:1, B >>.
还有你提供的REPL测试示例:
Eshell V9.3 (按^G终止) 1> c(bitutils). {ok,bitutils} 2> B = <<0:3>>. <<0:3>>
实现flip_bit/2函数
翻转位的逻辑很直接:先定位到目标位,取反它的值,再重新构造位串。这里有几种实现思路:
1. 基于你现有函数的基础实现
可以复用你已经写好的get_bit/2来获取当前位的值,取反后再构造新的位串:
flip_bit(Bin, N) -> CurrentBit = get_bit(Bin, N), NewBit = 1 - CurrentBit, % 0变1,1变0 << Pre:N/bitstring, _:1, Post/bitstring >> = Bin, << Pre/bitstring, NewBit:1, Post/bitstring >>.
2. 更高效的直接模式匹配实现
不用调用额外函数,直接通过模式匹配定位目标位并取反:
flip_bit(Bin, N) -> << Pre:N/bitstring, Bit:1, Post/bitstring >> = Bin, << Pre/bitstring, (1 - Bit):1, Post/bitstring >>.
3. 增加边界检查的健壮版
上面的实现如果传入无效的索引(比如超出位串长度)会抛出模糊的模式匹配异常,我们可以添加守卫子句来做参数校验,抛出更明确的错误:
flip_bit(Bin, N) when is_bitstring(Bin), N >= 0, N < bit_size(Bin) -> << Pre:N/bitstring, Bit:1, Post/bitstring >> = Bin, << Pre/bitstring, (1 - Bit):1, Post/bitstring >>; flip_bit(_Bin, N) -> error({invalid_bit_index, N}).
更新完整模块
把flip_bit/2添加到导出列表里,最终的模块代码如下:
-module (bitutils). -export ([get_bits/1, get_bit/2, set_bit/2, flip_bit/2]). get_bits(B) -> << <<X>> || <<X:1>> <= B >>. get_bit(Bin, N) when N >= 0, N < bit_size(Bin) -> << _:N/bitstring, Bit:1, _/bitstring >> = Bin, Bit; get_bit(_Bin, N) -> error({invalid_bit_index, N}). set_bit(Bin, N) when N >= 0, N < bit_size(Bin) -> << Pre:N/bitstring, _:1, Post/bitstring >> = Bin, << Pre/bitstring, 1:1, Post/bitstring >>; set_bit(_Bin, N) -> error({invalid_bit_index, N}). flip_bit(Bin, N) when is_bitstring(Bin), N >= 0, N < bit_size(Bin) -> << Pre:N/bitstring, Bit:1, Post/bitstring >> = Bin, << Pre/bitstring, (1 - Bit):1, Post/bitstring >>; flip_bit(_Bin, N) -> error({invalid_bit_index, N}).
测试示例
在REPL里测试一下翻转功能:
3> B1 = <<1:3>>. % 位串是 111 <<1:3>> 4> bitutils:flip_bit(B1, 0). % 翻转第0位,变成110 <<6:3>> 5> B2 = <<0:1,1:1,0:1>>. % 位串是010 <<2:3>> 6> bitutils:flip_bit(B2, 1). % 翻转第1位,变成000 <<0:3>> 7> bitutils:flip_bit(B2, 3). % 传入无效索引,抛出明确错误 ** exception error: {invalid_bit_index,3} in function bitutils:flip_bit/2 (bitutils.erl, line 18)
内容的提问来源于stack exchange,提问作者leifericf
相关产品推荐
相关产品推荐

