我正在尝试将非常长的二进制字符串(通常大于 52 位)转换为数字。我不能有一个固定的前瞻窗口,因为我这样做是为了计算神经数据的 Lempel-Ziv 复杂度的一个版本。
当我尝试转换任何长字符串时,bin2dec 会抛出二进制字符串必须为 52 位或更少的错误。
有没有办法绕过这个尺寸限制?
我正在尝试将非常长的二进制字符串(通常大于 52 位)转换为数字。我不能有一个固定的前瞻窗口,因为我这样做是为了计算神经数据的 Lempel-Ziv 复杂度的一个版本。
当我尝试转换任何长字符串时,bin2dec 会抛出二进制字符串必须为 52 位或更少的错误。
有没有办法绕过这个尺寸限制?
dec2bin
抛出该错误,因为单个无法存储那么高的精度。你的问题是不可能的。您有两个选择:将值存储在浮点值以外的其他值中,或者在转换之前丢弃一些精度。
或者更完整地描述你想要完成的事情。
编辑:
根据您的其他信息,我更加确定转换为浮点数不是您想要做的。如果您想将存储大小减小到更有效的程度,请转换为字节向量 (uint8),它尽可能密集。只需使用 reshape 将二进制字符串分成 N 行,每行 8 位。这似乎是生物数据的公认方法。
str = char((rand(1, 100)>0.5) + '0'); % test data
data = uint8(bin2dec(reshape(str(1:end-mod(end,8)), [], 8)));
在这段代码中,我将所有不均匀分成 8 的位扔掉。或者,跳过 uint8 步骤,只对结果向量执行处理,其中每个双精度浮点数代表序列中的一个 8 位字。
您可以推出自己的实现:
len = 60;
string = [];
for i = 1:len
string = [string sprintf('%d', randi([0 1]))];
end
% error
% bin2dec(string);
% roll your own...
value = 0;
for i = length(string):-1:1
value = value + str2num(string(i))*2^(length(string)-i);
end
我只是遍历字符串并添加一些值。最后, value 将包含字符串的十进制值。这对你有用吗?
注意:这个解决方案很慢。您可以通过预先分配字符串来加快速度,这是我在自己的机器上所做的。此外,如果您的号码达到 1e6 位,也会出现问题。此时,您需要可变精度算术来跟踪它。并将其添加到计算中确实减慢了速度。.mex
如果我是你,如果你需要 MATLAB 中的功能,我会强烈考虑从文件中编译它。
归功于@aardvarkk,但这是他算法的加速版本(+- 100x 快):
N=100;
strbin = char(randi(2,1,N)+'0'-1);
pows2 = 2.^(N-1:-1:0);
value=pows2*(strbin-'0')';
double
的范围只上升到1.79769e+308
哪个是2^1024
给予或接受。从那里开始,value
将是Inf
or NaN
。所以你仍然需要找到另一种存储结果数字的方法。
该算法的最后一个专家:您可以缓存pows2
大量数据,然后将其中的一部分用于长度为 N 的任何新 strbin:
Nmax = 1e8; % already 700MB for pows2, watch out!
pows2 = 2.^(Nmax-1:-1:0);
然后使用
value = pows2(Nmax-N+1:end)*(strbin-'0')';
File Exchange 上有一个名为 vpi 的工具:http: //www.mathworks.com/matlabcentral/fileexchange/22725
它允许您使用非常大的整数(2^5000
?没有概率)。在计算所有内容时它只会更慢(很多),我不建议使用我上面的方法。但是,嘿,你不能拥有一切!
下载软件包,addpath
它和以下可能会起作用:
N=3000;
strbin = char(randi(2,1,N)+'0'-1);
binvals=strbin-'0';
val=0;
twopow=vpi(1);
for ii=1:N
val=val+twopow*binvals(N-ii+1);
twopow=twopow*2;
end