2

我正在制作一个模拟器,它模拟处理器的乘法方法。事情是首先我必须将十进制形式转换为二进制,二进制表示的每一位都存储在数组中的单独位置。现在,如上所述存储在数组中的两个二进制数的乘法非常复杂,而且非常消耗内存。

因为我必须遵循这个方法;

1000

X

1110


   `0000`

  `1000`

 `1000`

`1000`

= 1110000

我知道我可以通过将小数形式相乘然后将它们转换为二进制来轻松做到这一点,但不幸的是,这里不需要。

我在想是否有办法将存储在数组中的二进制数存储为包含二进制数的单个整数。或任何其他将存储在数组中的二进制位相乘的简单方法。例如:

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], ETC。

当然缺点是你s[i]=='0'用来检查索引是否为'0'。

此外,我不会担心内存消耗,因为它并不是真正的,只是暂时的。请注意, std::string 是一个char-s 数组,它们是 8 位值,因此您的乘法(如果您有 8 个二进制数字)只需要 64bytes。这并不多,很容易放入最高级别的缓存中。

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

您可以将十进制数转换为包含 0 和 1 的数组(例如 32 位,模拟 32 位数字),然后将乘法代码写入两个这样的数组。

您将需要编写两个辅助函数,一个用于将十进制数转换为二进制(填充位数组),另一个用于将位数组转换为十进制数。

但据我了解,要求不涉及从十进制转换为二进制,反之亦然,只有二进制乘法,您可以使用整数数组简单地模拟二进制数:

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

在您的示例中,假设您要将二进制数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 回答