首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Erlang:将二进制数据转换为包含连续数个1的列表

Erlang:将二进制数据转换为包含连续数个1的列表
EN

Stack Overflow用户
提问于 2012-10-03 06:13:48
回答 3查看 558关注 0票数 1

%个问题

假设我有一个二进制数:

1011011101111011111

每个数字是一位。

我希望能够将其转化为:

1、11、111、1111、11111

...and最终进入:

1、2、3、4、5

我尝试的百分比

我尝试过binary:split,但是数据总是以位块的形式编码。我只想使用原始数据(如果可能的话)。

我想要完成的%

我正在为路由协议设计报头。我希望报头包含数据包已经访问过的地址列表。我认为,如果我给报头本身提供一个由0分隔的连续1组成的报头,我就不必对报头的总长度施加任何限制。标头的标头与标头本身之间将由两个连续的零分隔。因此,如果我有一个有效载荷,它说:

<<"Hello World">>

并且数据已被alice、bob和carl访问,则标头将为:

<<"alicebobcarl">>

标头的标头是:

(8*5一)0 (8*3一)0 (8*4一) 00

假设我们对报头使用了8位编码。

那么实际的数据包将会是:

(8*5 )0 (8*3 )0 (8*4 ) 00 <<"alicebobcarl">> <<"Hello World">>

为了破译报头,我将首先定位00的第一个实例,并将00之前的所有内容拆分为每个0。然后,我会将结果列表转换为一个列表,该列表包含数据包经过的每个地址中的位数。然后,我终于可以从报头中读取地址并检索有效负载。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-10-03 15:48:16

到resque的Bitstring comprehensions

代码语言:javascript
运行
复制
1> Inp = <<1:1,0:1,3:2,0:1,7:3>>.
<<"À">>
2> [ size(B) || B <- binary:split(<< <<I>> || <<I:1>> <= Inp >>, <<0>>, [global]) ].
[1,2,3]
票数 1
EN

Stack Overflow用户

发布于 2012-10-03 08:51:18

你能把二进制转换成字符串吗?

假设你可以,那么像下面这样做:

代码语言:javascript
运行
复制
B = "1011011101111011111",
S = string:tokens(B, "0"),
R = lists:map(fun(E)->length(E) end, S).

但这并不是很有效。期待好的答案。

票数 1
EN

Stack Overflow用户

发布于 2012-10-03 14:42:33

下面是解析header的方法:

代码语言:javascript
运行
复制
-module(bitcnt).
-export([parse_header/1]).

parse_header(Message) ->
        parse_header(Message, []).

parse_header(<<0:1, 0:1, Body/bitstring>>, Header) ->
        %% stop if found header delimiter - two consecutive zero bits
        %% return parsed header and message body
        {lists:reverse(Header), Body};
parse_header(<<1:1, Rest/bitstring>>, []) ->
        %% handle if first bit is '1'
        parse_header(Rest, [1]);
parse_header(<<1:1, Rest/bitstring>>, [H | T]) ->
        %% handle consecutive '1' bits of header
        parse_header(Rest, [H+1 | T]);
parse_header(<<0:1, Rest/bitstring>>, Header) ->
        %% handle delimiters inside header - '0' bit
        parse_header(Rest, [0 | Header]).

让我们在shell中测试它。假设标题'10110111‘(必须解析为1,2,3) +分隔符'00’+某个正文<<12345:64>>:

代码语言:javascript
运行
复制
2> B1 = <<1:1,0:1,1:1,1:1,0:1,1:1,1:1,1:1,0:1,0:1,12345:64>>.
<<183,0,0,0,0,0,0,12,14,1:2>>
3> 
3> bitcnt:parse_header(B1).
{[1,2,3],<<0,0,0,0,0,0,48,57>>}
4> 
4> <<12345:64>>.
<<0,0,0,0,0,0,48,57>>

另一个测试'11101‘(必须解析为3,1) + '00’+ <<12345:64>>

代码语言:javascript
运行
复制
5> B2 = <<1:1, 1:1, 1:1, 0:1, 1:1, 0:1, 0:1, 12345:64>>.
<<232,0,0,0,0,0,0,96,57:7>>
6> 
6> bitcnt:parse_header(B2).                             
{[3,1],<<0,0,0,0,0,0,48,57>>}

即使报头为空(消息以两个连续的0比特开始)-函数将报头解析为空列表:

代码语言:javascript
运行
复制
7> B3 = <<0:1, 0:1, 12345:64>>.
<<0,0,0,0,0,0,12,14,1:2>>
8> 
8> bitcnt:parse_header(B3).    
{[],<<0,0,0,0,0,0,48,57>>}

P.S.

顺便说一句,你的报头的格式是非常冗余的。如果你想编码大数字,例如,数字1024 -你需要把它转换成1024个连续的'1‘位!

有两种方法可以改进标头的格式:

  • 如果您知道您的任何数字小于某个阈值数字:计算您需要对具有最大值的数字进行编码的位数,并使用预定义长度的位串对报头中的每个数字进行编码。例如,如果你所有的数字都小于2^32,你需要32位来对这个区间中的每个数字进行编码,如果你不能定义阈值(具有最大值的数字):

variable length

  • 。例如,Elias gamma-codingExponential-Golomb coding.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12699167

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档