【问题标题】:perl-how to treat a string as a binary number?perl-如何将字符串视为二进制数?
【发布时间】:2014-07-30 03:26:58
【问题描述】:

读取包含地址和数据的文件,如下所示:

@0, 12345678
@1, 5a5a5a5a
...

我的目标是读取地址和数据。考虑我读取的数据是十六进制格式,然后我需要将它们解包为二进制数。 所以12345678 会变成00010010001101000101011001111000 然后,我需要将传输的二进制数进一步解包到另一个级别。 所以它变成了,
00000000000000010000000000010000000000000001000100000001000000000000000100000001000000010001000000000001000100010001000000000000

他们的做法如下所示

while(<STDIN>) {
 if (/\@(\S+)\s+(\S+)/) {
    $addr = $1;
    $data = $2;
    $mem{$addr} = ${data};
 } 
}

foreach $key (sort {$a <=> $b} (keys %mem)) {

  my $str = unpack ('B*', pack ('H*',$mem{$key}));
  my $str2 = unpack ('B*', pack ('H*', $str));
  printf ("@%x ", $key);
  printf ("%s",$str2);
  printf ("\n"); 
}

它有效,但是,我的下一步是对传输的位进行一些数字运算。 例如按位或和移位。我试过

如果您有更好的想法,请留下您的 cmets。谢谢。

【问题讨论】:

  • 先做算术,然后转换成一串一和零。
  • tripleee:我想对最后的 256bits 二进制数做一个移位,我不知道怎么做。
  • 是的,在实际数字上,而不是在它们的字符串表示上。而不是“unpack; unpack; shift”做“unpack; shift; unpack”。
  • 你能举个例子吗?
  • @tripleee 如果不使用一些bigint 库,您不能简单地对 256 位数字进行算术运算。

标签: perl


【解决方案1】:

您可以使用 metaCPAN 中的Bit::Vector 模块

use strict;
use warnings;
use Bit::Vector;

my $str = "1111000011011001010101000111001100010000001111001010101000111010001011";
printf "orig str: %72s\n", $str;

#only 72 bits for better view
my $vec = Bit::Vector->new_Bin(72,$str);
printf "vec     : %72s\n", $vec->to_Bin();

$vec->Move_Left(2); 
printf "left 2  : %72s\n", $vec->to_Bin();

$vec->Move_Right(4); 
printf "right 4 : %72s\n", $vec->to_Bin();

打印:

orig str:   1111000011011001010101000111001100010000001111001010101000111010001011
vec     : 001111000011011001010101000111001100010000001111001010101000111010001011
left 2  : 111100001101100101010100011100110001000000111100101010100011101000101100
right 4 : 000011110000110110010101010001110011000100000011110010101010001110100010

如果您需要做一些任意精度的数学运算,您也可以使用Math::BigIntuse bigint (http://perldoc.perl.org/bigint.html)

【讨论】:

    【解决方案2】:

    十六进制和二进制是数字的文本表示。移位和位操作是数字操作。你需要一个数字,而不是文本。

    my $hex = '5a5a5a5a';
    $num = hex($hex);               # Convert to number.
    $num >>= 1;                     # Manipulate the number.
    $hex = sprintf('%08X', $num);   # Convert back to hex.
    

    在评论中,您提到要处理 256 位数字。本机数字不支持,但您可以使用 Math::BigInt。

    【讨论】:

    • 您能否添加一些使用 Math::BigInt 对 96 位(12 字节)数字进行移位(左右)的示例,例如结果也应该是96位?
    • @kobame,您可以像往常一样使用&lt;&lt;&amp;
    • $b &lt;&lt;= 1$b &amp; $mask 都可以。但是如何从$b-&gt;as_bin() 打印出空填充的二进制字符串,长度为 96 个字符?
    • @kobame, sprintf('%096s', substr($num-&gt;as_bin(), 2))
    • 谢谢。现在知道了 - 需要使用 substr 与移位量。
    【解决方案3】:

    我对此的最终解决方案是忘记将它们视为数字,将它们视为字符串。我使用子字符串和字符串浓度而不是移位。然后对于 or 操作,我只是将字符串的每一位相加,如果为 0,则结​​果为 0,否则为 1。

    这可能不是解决此问题的最佳方法。但这就是我最终使用的方式。

    【讨论】:

      猜你喜欢
      • 2012-05-07
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-12
      • 2017-07-21
      • 1970-01-01
      • 2021-02-24
      相关资源
      最近更新 更多