Functional programming 如何在Erlang二进制文件中有效地一次设置一位,而不必执行命令?

Functional programming 如何在Erlang二进制文件中有效地一次设置一位,而不必执行命令?,functional-programming,erlang,bytearray,Functional Programming,Erlang,Bytearray,作为一个练习,我正在研究埃拉托什尼筛的并行实现。作为其中的一部分,我正在实现一系列位图,每个数字使用一位来节省内存。一次读取一个位似乎工作正常,但设置它们的速度很慢,特别是当我使用大型二进制文件时 getBit(Bin, N, Size)-> R=Size-N-1, <<_:N,Bit:1,_:R>> = Bin, Bit. setBit(Bin, N, Size)-> R=Size-N-1, <<A:N,

作为一个练习,我正在研究埃拉托什尼筛的并行实现。作为其中的一部分,我正在实现一系列位图,每个数字使用一位来节省内存。一次读取一个位似乎工作正常,但设置它们的速度很慢,特别是当我使用大型二进制文件时

getBit(Bin, N, Size)->
    R=Size-N-1,
    <<_:N,Bit:1,_:R>> = Bin,
    Bit.

setBit(Bin, N, Size)->
    R=Size-N-1,
    <<A:N,_:1,B:R>> = Bin,
    <<A:N,1:1,B:R>>.
getBit(Bin,N,Size)->
R=尺寸-N-1,
=Bin,
一点
收件箱(箱、N、尺寸)->
R=尺寸-N-1,
=Bin,
.
有没有一种方法可以在函数式Erlang中很好地做到这一点,也许类似于数组的工作方式?
我已经读过关于hipe\u bifs:bytearray\u update的文章,但我更愿意保持我的编码风格的功能性。

一般来说,对于
get
set
操作来说,对于复杂度为
O(log(n))
的Erlang是一种函数式语言。您可以使用某种类型的树来归档
O(log(n))
<代码>数组,
dict
gb\u树
gb\u集
模块执行此操作


因此,如果您需要尽可能快地完成,您必须执行命令-您可以尝试使用
hipe_bifs
模块、处理字典和
ets
表格。

您可以将位图存储为整数(如果它们不超过~1000位):


您可以尝试您的版本,但不传递大小,并填充到字节:

getBit(Bin, N)->
    <<_:N/bitstring,Bit:1,_/bitstring>> = Bin,
    Bit.

setBit(Bin, N)->
    <<A:N,_:1,B/bitstring>> = Bin,
    <<A:N,1:1,B>>.

%OR:
setBit(Bin, N)->
    PSize = 8 - ((N + 1) rem 8),
    <<A:N,_:1, Pad:PSize,B/bytes>> = Bin,
    <<A:N,1:1,Pad:PSize,B>>.
getBit(Bin,N)->
=Bin,
一点
收件箱(箱,N)->
=Bin,
.
%或:
收件箱(箱,N)->
PSize=8-((N+1)rem 8),
=Bin,
.

可能更好,也可能更糟:-)

只要您能够正常工作,每次更改一点都必须复制您的位字符串。如果您更改为其他功能性数据结构,则不需要复制整个结构……因为浮动不够大,所以无法工作。从使用浮点数改为1 bsl B。它稍微快一点,但需要更多内存,所以我不能存储那么多位,仍然是O(n)。这仍然是一个好主意,如果Erlang bignums专门处理两个的异能,它可能会起作用。(正如Erlang在允许程序员使用函数样式时所做的那样)当我尝试使用
setBit
(Erlang/OTP 20)的这个实现时,我收到一个错误的参数异常。将值为
的变量
B
传递给它,如下所示:
setBit(B,0)。
试图找出原因,我现在有点不知所措(我对此非常陌生)。谢谢,我找到了hipe\u bifs:bitarray、bitarray\u sub和bitarray\u update。我想我必须将这些用于筛选,然后用它来推动Erlang的开发人员将优化包括在系统中,这样我就可以使用功能风格并高效地执行。进程字典我看不出这里的意义,ets表不是一个很好的匹配。
getBit(Bin, N)->
    <<_:N/bitstring,Bit:1,_/bitstring>> = Bin,
    Bit.

setBit(Bin, N)->
    <<A:N,_:1,B/bitstring>> = Bin,
    <<A:N,1:1,B>>.

%OR:
setBit(Bin, N)->
    PSize = 8 - ((N + 1) rem 8),
    <<A:N,_:1, Pad:PSize,B/bytes>> = Bin,
    <<A:N,1:1,Pad:PSize,B>>.