【问题标题】:Convert binary string greater than 52 bits to single in Matlab?在Matlab中将大于52位的二进制字符串转换为单个字符串?
【发布时间】:2012-09-11 03:42:49
【问题描述】:

我正在尝试将非常长的二进制字符串(通常大于 52 位)转换为数字。我不能有一个固定的前瞻窗口,因为我这样做是为了计算神经数据的 Lempel-Ziv 复杂度版本。

当我尝试转换任何长字符串时,bin2dec 会抛出二进制字符串必须为 52 位或更少的错误。

有没有办法绕过这个大小限制?

【问题讨论】:

  • 您需要多少精度?最大位数是多少?
  • 未知。这是一个研究项目的一部分。无论如何,我估计我需要转换最多长度为 1e6 的二进制字符串。尽可能接近它会很棒。不过我可能会遗漏一些东西,因为我注意到 ceil(log2(1e6)) 只有 20。
  • 1e6 位表示 pow(2,1e6) 的值,它是大约 10^300000 的十进制值。你确定你需要处理这么大的数字(即远大于宇宙中基本粒子的数量)吗?
  • 我将传递给像 dec2bin 这样的函数的字符串长度可能与 1e6 一样长。它来自每秒对一个过程进行 1e4 次采样,我预计模式将持续大约 100 秒。我使用二进制字符串的十进制值作为哈希来构建查找表以计算 LZ 复杂度。
  • 您确定您使用的是dec2bin 而不是bin2decdec2bin 将数字转换为二进制,而不是将二进制字符串转换为数字...

标签: matlab numerical-methods


【解决方案1】:

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 位字顺序。

【讨论】:

  • 我请求帮助找到解决办法。
  • 您的额外 cmets 有助于明确您的目标。见编辑。
【解决方案2】:

您可以推出自己的实现:

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 位,也会出现问题。此时,您需要可变精度算术来跟踪它。并将其添加到计算中真的会减慢速度。如果我是你,如果你需要 MATLAB 中的功能,我会强烈考虑从 .mex 文件编译它。

【讨论】:

    【解决方案3】:

    感谢@aardvarkk,但这是他的算法的加速版本(快了+- 100 倍):

    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 将变为 InfNaN。所以你仍然需要找到另一种存储结果数字的方法。

    该算法的最后一个专家:您可以缓存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')';
    

    matlab的数值上限解

    文件交换上有一个名为 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
    

    【讨论】:

    • 请注意,双精度只有 52 位(这可能是 bin2dec 中 52 位限制的来源)。
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2014-08-02
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 2019-03-14
    相关资源
    最近更新 更多