2

プロセッサの乗算方法をシミュレートするシミュレータを作成しています。まず、10進数形式をバイナリに変換する必要があります。バイナリ表現の各ビットは、配列内の別々の場所に格納されます。現在、上記のように配列に格納されている2つの2進数の乗算は非常に複雑であり、メモリを非常に消費します。

私はこの方法に従わなければならないからです。

1000

バツ

1110


   `0000`

  `1000`

 `1000`

`1000`

= 1110000

小数の形式を掛け合わせてから2進数に変換することで、これを簡単に実行できることはわかっていますが、残念ながら、ここでは必要ありません。

配列に格納されている2進数を、2進数を含む1つの整数として格納する方法があるかどうかを考えていました。または、配列に格納されているバイナリビットを乗算するその他の簡単な方法。例えば:

a[0]=1,a[1]=1, .... ,a[32]=0

整数変数に含める必要があります

int x=110....0

これを行う方法はありますか?

よろしく

4

6 に答える 6

9

std::bitsetを使用できます

std::bitset<32> b;

b[0] = 1;
b[1] = 1;
...
于 2012-11-29T16:28:28.187 に答える
4

これは私が使用するトリックであり、ビットマスクがビットが設定されているかどうか、またはビットを設定/リセットするかどうかをテストするのに非常に便利です。私はそれがあなたにかなり役立つかもしれないと思います。(時々私は自分自身をクラックします。)

template <std::size_t bitIndex, typename T>
bool get_integer_bit(const T num)
{
    // Make sure what was passed in is something ilke an int or long.
    static_assert(std::numeric_limits<T>::is_integer, "Numeral argument must be an integer type.");

    // Don't go out of bounds of the size of the number.
    static_assert(bitIndex < std::numeric_limits<T>::digits + std::numeric_limits<T>::is_signed, "bitIndex is out of bounds for type T");
    static_assert(bitIndex >= 0, "bitIndex is out of bounds for type T");

    // Rip the bit out of the number.
    return ((0x1 << bitIndex) & num) != 0;
}

template <std::size_t bitIndex, typename T>
void set_integer_bit(T& num, const bool bitValue)
{
    // Make sure what was passed in is something ilke an int or long.
    static_assert(std::numeric_limits<T>::is_integer, "Numeral argument must be an integer type.");

    // Don't go out of bounds of the size of the number.
    static_assert(bitIndex < std::numeric_limits<T>::digits + std::numeric_limits<T>::is_signed, "bitIndex is out of bounds for type T");
    static_assert(bitIndex >= 0, "bitIndex is out of bounds for type T");

    // Set the bit into the number.
    if (bitValue)
        num |= (0x1 << bitIndex); // Set bit to 1.
    else
        num &= ~(0x1 << bitIndex); // Set bit to 0.
}

そして使用法については...

// Test get_integer_bit.
std::cout << set_integer_bit<0>(1);  // Pulls the first (0th) bit out of the integer 1. Result should be 1
std::cout << set_integer_bit<1>(1);  // Pulls the second bit out of the integer 1. Result should be 0
std::cout << set_integer_bit<33>(2); // error C2338: bitIndex is out of bounds for type T

// Test set_integer_bit.
std::cout << get_integer_bit<0>(test); // Should be 0.
set_integer_bit<0>(test, 1); // Set the first (0th) bit to a 1 (true).
std::cout << get_integer_bit<0>(test); // Should be 1, we just set it.

これは、あらゆる種類のintのサイズで機能し、ビットのインデックスが指定された型の範囲外にある場合、コンパイル時に文句を言うという利点があります。ただし、それより少し多くを探していて、型のビットにもっと動的にアクセスしたい場合は、std::bitsetを使用する必要があります。

于 2012-11-29T17:08:29.933 に答える
2

@JohnBandelaの答えは、ビットセットからロング(または文字列)に前後に変換する方法に関する情報で完成させることができます。

次のように、配列のように動作するビットセット を前後に変換できます。

#include<bitset>
#include<string>
#include<iostream>
using namespace std;
const int N_DIGITS = 8;

// easy initialization:

// from unsigned long
unsigned long num = 8ul; // == 1000 in binary form
bitset<N_DIGITS> bs1(num);

// from string
string s_num = "1110";
bitset<N_DIGITS> bs2(s_num);

// extraction & printing:

cout << "Binary value of bs1:"  << bs1.to_string() << endl;  // ... "1000"
// ...or just...
cout << "Binary value of bs1:"  << bs1             << endl;
cout << "Decimal value of bs2:" << bs2.to_long()   << endl;  // ... "20"

ビット演算子:

基本的な二項演算子を気にする必要がない場合に備えて、便利な演算子のリストを示します。できるよ:

// every operator comes in "bs1 &= bs2" and "bs1 & bs2" form. 

bs1 &= bs2; bs1|=bs2; bs1^=bs2; // the last one is xor
~bs1; // negating

size_t n=5;
bs1<<=n; bs1>>=n;     // bit-shifts, n is the amount of bit locations to be shifted.

bs1==bs2;  bs1!=bs2;  // comparisons

これにより、乗算シミュレーションの実装がはるかに簡単になります。

于 2012-11-30T01:59:09.020 に答える
1

フォーカスの内容によっては、std :: string-s(およびstd :: stringstream-s)を使用することもできます。これは、バイナリ形式への変換とバイナリ形式からの変換が非常に簡単で、インデックス付きアクセスも使用できるためです。

std::string s; s[0], s[1]、など。

もちろん、欠点はs[i]=='0'、インデックスが「0」であるかどうかをチェックするために使用することです。

また、メモリの消費量はそれほど多くなく、一時的なものであるため、心配する必要はありません。std :: stringはchar8ビット値である-sの配列であるため、乗算(2進数が8桁の場合)に必要なのは64バイトのみであることに注意してください。それはそれほど多くはなく、最高レベルのキャッシュに簡単に収まります。

Series  Intel Core i5/i7
Level 1 Cache   128 KB <- this is the interesting part for you, should be larger than 6k, ok.
Level 2 Cache   512 KB
Level 3 Cache   3072 KB(i5) 4096 KB(i7)

出典:ノートブックチェック

于 2012-11-29T16:35:54.977 に答える
0

10進数を0と1を保持する配列(たとえば、32桁、32ビット数をシミュレート)に変換してから、そのような2つの配列に乗算コードを書き込むことができます。

2つのヘルパー関数を作成する必要があります。1つは10進数の2進数を変換する(ビット配列を埋める)ためのもので、もう1つはビット配列から10進数に変換するためのものです。

しかし、私が理解しているように、要件には10進数から2進数への変換は含まれず、その逆も含まれます。2進数の乗算のみで、整数配列を使用して2進数をシミュレートできます。

int binary_1[8] = {0, 0, 0, 1, 0, 0, 1, 1};
int binary_2[8] = {0, 1, 0, 0, 0, 0, 1, 1};
于 2012-11-29T16:29:46.167 に答える
-2

ユニオンを使用してこれを実現できます。

typedef union { 
    int x;
    struct {
        char b1: 1;
         ....
        char b32: 1;
    }y;
}bits;

この構文は、配列のインデックス作成ほど優れていませんが、データ型自体への簡単な入力が可能です。

bits a; a.x = 100;

あなたがそれをどのように使うかなら、あなたはそのようなビットに到達するでしょう。

a.y.b1

あなたの例では、2進数1001をタイプに入れたいとbitsしましょう。次のようにします。

a.x = 0;//clear all the bits
a.y.b1 = 1;//set first bit
a.y.b2 = 0;//clear second bit
a.y.b3 = 0;//clear third bit
a.y.b4 = 1;//set fourth bit

上記は定義されておらず、実装固有であるため、信頼性がありません。より良い方法は、特定のビットを設定/クリアする関数/マクロを使用することです。

OPの元の質問ではa[0] = 1、上記の回答と同様の構文が必要だったため、コメントで提示されているように動作は標準で定義されていませんが、同様の構文が提供されます。

于 2012-11-29T16:24:55.380 に答える