1

%问题
假设我有一个二进制数:
1011011101111011111
每个数字都是一位。

我希望能够将其转换为:
[1, 11, 111, 1111, 11111]

...并最终进入:
[1, 2, 3, 4, 5]

%我试过什么我
试过二进制:split,但数据总是以比特块编码。我只想处理原始数据(如果可能的话。)

%我要完成的工作
我正在为路由协议设计标头。我希望标头包含数据包已经访问过的地址列表。我想如果我给标题本身一个由零分隔的连续的标题组成的标题,我就不必对标题的总长度施加任何限制。标头的标头将通过两个连续的零与标头本身分开。因此,如果我有一个有效负载,上面写着:
<<"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。然后我会将结果列表转换为一个列表,其中包含数据包经过的每个地址中的位数。然后我终于可以从标头中读取地址并检索有效负载。

4

3 回答 3

1

对 resque 的位串理解:

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]
于 2012-10-03T07:48:16.467 回答
1

你可以将二进制转换为字符串吗?

假设您可以,然后执行以下操作:

B = "1011011101111011111",
S = string:tokens(B, "0"),
R = lists:map(fun(E)->length(E) end, S).

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

于 2012-10-03T00:51:18.380 回答
0

这是解析标头的方法:

-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>>:

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>>

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>>}

即使标头为空(消息以两个连续的零位开头) - 函数将标头解析为空列表:

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>>}

附言

顺便说一句,您的标题格式非常多余。如果您想编码大数字,例如数字 1024 - 您需要将其转换为 1024 个连续的“1”位!

有两种方法可以改善标题格式:

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

  • 如果您无法定义阈值(具有最大值的数字):使用可变长度编码。例如,Elias 伽玛编码指数哥伦布编码

于 2012-10-03T06:42:32.657 回答