0

次のような800行を含むファイルがあります。

id       binary-coded-info
---------------------------
4657     001001101
4789     110111111
etc.

ここで、それぞれ 0 または 1 は何らかの機能の存在を表します。このファイルを読み取り、バイナリ コード化された情報に対していくつかのビット単位の論理演算を実行したいと考えています (演算は、ユーザー入力と 3000 行の 2 番目のファイルからの情報に依存します)。次に、これらの再計算されたバイナリ コード化された情報をファイルに書き込む必要があります (末尾にゼロを付けて、たとえば

4657     000110011
4789     110110000
etc.

独自の基数変換ルーチンを作成せずにこれを行うにはどうすればよいですか? 私は何に対してもオープンです。Python、perl など、私が知らない言語も受け入れます。コンパイルせずに動作するはずです。

これまでのところ、私は自分のやり方でスクリプトを作成し、awk し、sed しようとしました。これは(私が思うに)次のことを意味します:base-2としてバッチ読み取り、base-10に変換、ユーザー入力と2番目のファイルに応じてビット単位の操作を実行、base-2に変換、先行ゼロを追加して出力。ファイルに多くの行があるため、bc を使用するための通常のコンソール ヒントはエレガントに見えません。dc.sed についても同様です。また、 awk には、入力にバイナリとしてフラグを付けるのと同等の機能がないようです( "echo $((2#101010))" のように)。 また、printf トリックはバイナリでは機能しません。では、これを最もエレガントに行うにはどうすればよいでしょうか?

4

6 に答える 6

3

なぜそれらを変換してビット操作を使用するのですか?

Python では、これらすべてを文字列として実行できます。

for line in myFile:
    key, value = line.split()
    bits = list(value)
    # bits will be a list of 1-char strings ['1','0','1',...]
    # ... do stuff to bits ...
    print key, "".join( value )
于 2009-04-14T21:10:10.340 に答える
1

Python では、基数 2 を指定して、int を使用してバイナリに変換できます。

>>> int('110111111',2)
447

元に戻すには、binpython2.6 または 3 には関数がありますが、python2.5 にはありません。そのため、自分で実装する必要があります (または以下のようなものを使用します)。

def bin(x, width):
    return ''.join(str((x>>i)&1) for i in xrange(width))[::-1]

>>> bin(447, 9)
110111111

(幅はパディングする桁数です - あなたの例は9ビットの数字を使用しているようです。)

于 2009-04-14T22:33:40.140 に答える
0

C では、既に C で変換を行っている場合は、"strtol(str, NULL, 2)" を使用して変換を行うことができます。

次のようなものが機能します。

FILE* f = fopen("myfile.txt", "r");
char line[1024];
while ((line = fgets(line, sizeof(line), f))
{
  char* p;
  long column1 = strtol(line, &p, 10);
  long column2 = strtol(p, &p, 2);
  ...
}

エラー処理などを追加する必要があります。

于 2009-04-14T21:05:30.197 に答える
0

そして、長い伝統に従って、ここに awk バージョンがあります :-)
gawk 4.0.1 で最後にチェックされ
ました。他の awk でも同様に動作するはずです。

{
      var = _int("00010101",2);
      print _bin( or( var ,  _int("00101001",2) ) , 8 ) 
      print _bin( and( var , _int("10110111",2) ) , 8 ) 
      print _bin( xor( var ,var ) , 8 );
}    

# convert var to d-ht base. Specify 16 for hex, 8 for oct, and such. Up to base 36, for fruther base, provide X. if d<=36, and wish to use custom X, provide 1 for i.
function _obase( v , d , X , i, this , r ){
  if(d<=9){r="";while(v){r=v%d""r;v=int(v/d)};return r;}
  if(d<=36&&!i){for(i=0;i<=9;i++)X[i]=""i;for(;i<d;i++)X[i]=sprintf("%c",55+i);}
  r="";while(v){r=X[v%d]""r;v=int(v/d)};return r;
}
function _pad(d, p, w, this ,r){
  r=""d;while(length(r)<w)r=p""r;return r;
}
function _bin( v , w , this ){
  return _pad(_obase(v,2),"0",w);
}
# convert string to var, using d as base. for base>36, specify X. if wish to use custom X, provide 1 to i
function _int( s , d , X , i , this , k , r ){
  r=0;k=length(s);if(d<=9){for(i=1;i<=k;i++){r*=d;r=r+int(substr(s,i,1));}return r;}
  if(d<=36&&!i){for(i=0;i<=9;i++)X[""i]=i;for(;i<d;i++)X[sprintf("%c",55+i)]=i;}
    for(i=1;i<=k;i++){r*=d;r=r+X[substr(s,i,1)];}eturn r;
}

関数 and()、or()、xor() は、一部のタイプの awk で欠落している可能性があります。その場合は、ビット操作ライブラリをロードします。awk 用のものがいくつかネットに浮かんでいます。または、独自のものを提供します。

于 2012-08-19T13:36:10.110 に答える
0

「単純な」Perl ワンライナー (foo bar baz quux をフラグに置き換えます

perl -le '@f=qw/foo bar baz quux/;$_&&print($f[$i]),$i++for split//, shift' 1011

読み取り可能な Perl バージョンは次のとおりです。

#!/usr/bin/perl

use strict;
use warnings;

#flags that can be turned on and off, the first 
#flag is turned on/off by the left-most bit
my @flags = (
    "flag one",
    "flag two",
    "flag three",
    "flag four",
    "flag five",
    "flag six",
    "flag seven",
    "flag eight",
);

#turn the command line argument into individual
#ones and zeros
my @bits = split //, shift; 

#loop through the bits printing the flag that
#goes with the bit if it is 1
my $i = 0;
for my $bit (@bits) {
    if ($bit) {
        print "$flags[$i]\n";
    }
    $i++;
}
于 2009-04-14T22:34:54.617 に答える
0

ブライアンの答えを拡張する:

# Get rid of the '----' line for simplicity
data_file = '''id       binary-coded-info
4657     001001101
4789     110111111
'''
import cStringIO
import csv, sys
data = [] # A list for the row dictionaries (we could just as easily have used the regular reader method)
# Read in the file using the csv module
# Each row will be a dictionary with keys corresponding to the first row
reader = csv.DictReader(cStringIO.StringIO(data_file), delimiter=' ', skipinitialspace = True)
try:
    for row in reader:
        data.append(row) # Add the row dictionary to the data list
except csv.Error, e:
    sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))
# Do something with the bits
first = int(data[0]['binary-coded-info'],2) # First bit string
assert(first & int('00001101',2) == int('1101',2)) # Bitwise AND
assert(first | int('00001101',2) == int('1001101',2)) # Bitwise OR
assert(first ^ int('00001101',2) == int('1000000',2)) # Bitwise XOR
assert(~first == int('110110010',2)) # Binary Ones Complement
assert(first << 2 == int('100110100',2)) # Binary Left Shift
assert(first >> 2 == int('000010011',2)) # Binary Right Shift

csvモジュールの詳細については、csv モジュールを参照してください。

于 2009-04-14T23:34:27.780 に答える