如何定义和与位用C数组工作? [英] How to define and work with an array of bits in C?

查看:130
本文介绍了如何定义和与位用C数组工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建上,我写0和1的一个非常大的数组。我试图模拟称为随机顺序吸附,其中,长度为2的单元,二聚体,是在随机位置沉积到一个n维点阵的物理过程,互不重叠。当没有更多的空间留在晶格用于沉积更多二聚体(晶格被卡住)的过程中停止。

最初我开始用零的晶格,并且二聚体重新由一对'1'psented $ P $。由于每个二聚物沉积,对二聚体的左侧的部位被阻止,由于这样的事实,该二聚体不能重叠。所以,我模拟通过沉积三'1对晶格这个过程。我需要重复整个模拟了大量的时间,然后制定出平均覆盖率%。

我一直在使用的字符为一维和二维晶格阵列已经做到了这一点。目前,我试图让code尽可能有效,对3D问题,更复杂的工作概括之前。

这基本上是code看起来像一维,简化为:

  INT的main()
{
    / *定义格* /
    阵列=(字符*)malloc的(N * sizeof的(炭));    total_c = 0;    / *开展RSA多次* /
    对于(i = 0; I< 1000;我++)
        rand_seq_ads();    / *在干扰计算平均覆盖率效率* /
    的printf(覆盖效率=%LF,total_c / 1000);    返回0;
}无效rand_seq_ads()
{
    / *初始化数组,初始条件* /
    memset的(一,0,N *的sizeof(字符));
    available_sites = N;
    计数= 0;    / *当晶格仍然有足够的空间... * /
    而(available_sites!= 0)
    {
        / *生成随机选址* /
        X = RAND();        / *存款二聚体(如果网站可用)* /
        如果(阵列[X] == 0)
        {
            数组[X] = 1;
            数组[X + 1] = 1;
            数+ = 1;
            available_sites + = -2;
        }        / *左二聚体不可用(如果为空)马克网站* /
        如果(阵列[X-1] == 0)
        {
            阵列[X-1] = 1;
            available_sites + = -1;
        }
    }    / *计算覆盖率%,加总* /
    C =计数/ N
    total_c + = C;
}

有关实际的项目我做,它不仅涉及二聚体,但三聚体,quadrimers,和(2D和3D),各种形状和大小。

我希望我能够与各个位而不是字节的工作,但我一直在阅读和周围据我可以告诉你只能更改一次1个字节,所以无论是我需要做的一些复杂的索引或者有一个简单的办法做到这一点?

谢谢您的回答


解决方案

 的typedef unsigned long类型bfield_t [size_needed /的sizeof(长)];
//长,因为这可能是你的CPU是最擅长什么
//该size_needed应该是均匀的sizeof divisable(长)或
//你可能(的sizeof(长)-1 + size_needed)/的sizeof(长),以迫使其围捕

现在,每个长在bfield_t可以容纳的sizeof(长)* 8位。

您可以计算的指数需要通过大的:

  bindex =指数/(8 * sizeof的(长));

您位数

  B =索引%(8 * sizeof的(长));

您可以再看看长期需要,然后屏蔽掉你需要它的位。

 结果= my_field [bindex]放大器; (1 <<;&下; B);

 的结果= 1&安培; (my_field [bindex]≥&GT; B); //如果preFER他们在位0

第一种可能是某些CPU更快,可以节省你转移备份的需要
在多个比特列执行相同的位之间的操作。它还镜子
在外地位的设置和清除比更加紧密第二FPGA实现。
设置:

  my_field [bindex] | = 1&LT;&LT; B;

明确的:

  my_field [bindex&安培; =〜(1 <<;&LT; B);

您应该记住,你可以在持有领域的多头使用位操作
这就是同在个别位的操作。

您或许还需要(如果可用)寻找到了农民田间学校,FLS,FFC和FLC等功能。农民田间学校应始终 strings.h 缴费。它的存在只是为了这个目的 - 位的字符串。
无论如何,这就是找到先设置基本上是:

  INT FFS(INT X){
    INT C = 0;
    而((X安培;!1)){
        C ++;
        X - GT;&GT; = 1;
    }
    返回℃; //除了它处理X = 0不同
}

这是一种常见的操作处理器有一个指令和你的编译器可能会产生的指令,而不是调用像我写了一个函数。 86有这样的指令,顺便说一句。哦,民丰金融和ffsll是相同的功能,除了需要很长时间和很长很长,分别为。

I want to create a very large array on which I write '0's and '1's. I'm trying to simulate a physical process called random sequential adsorption, where units of length 2, dimers, are deposited onto an n-dimensional lattice at a random location, without overlapping each other. The process stops when there is no more room left on the lattice for depositing more dimers (lattice is jammed).

Initially I start with a lattice of zeroes, and the dimers are represented by a pair of '1's. As each dimer is deposited, the site on the left of the dimer is blocked, due to the fact that the dimers cannot overlap. So I simulate this process by depositing a triple of '1's on the lattice. I need to repeat the entire simulation a large number of times and then work out the average coverage %.

I've already done this using an array of chars for 1D and 2D lattices. At the moment I'm trying to make the code as efficient as possible, before working on the 3D problem and more complicated generalisations.

This is basically what the code looks like in 1D, simplified:

int main()
{
    /* Define lattice */
    array = (char*)malloc(N * sizeof(char));

    total_c = 0;

    /* Carry out RSA multiple times */
    for (i = 0; i < 1000; i++)
        rand_seq_ads();

    /* Calculate average coverage efficiency at jamming */
    printf("coverage efficiency = %lf", total_c/1000);

    return 0;
}

void rand_seq_ads()
{
    /* Initialise array, initial conditions */
    memset(a, 0, N * sizeof(char));
    available_sites = N;
    count = 0;

    /* While the lattice still has enough room... */
    while(available_sites != 0)
    {
        /* Generate random site location */
        x = rand();

        /* Deposit dimer (if site is available) */
        if(array[x] == 0)
        {
            array[x] = 1;
            array[x+1] = 1;
            count += 1;
            available_sites += -2;
        }

        /* Mark site left of dimer as unavailable (if its empty) */
        if(array[x-1] == 0)
        {
            array[x-1] = 1;
            available_sites += -1;
        }
    }

    /* Calculate coverage %, and add to total */
    c = count/N
    total_c += c;
}

For the actual project I'm doing, it involves not just dimers but trimers, quadrimers, and all sorts of shapes and sizes (for 2D and 3D).

I was hoping that I would be able to work with individual bits instead of bytes, but I've been reading around and as far as I can tell you can only change 1 byte at a time, so either I need to do some complicated indexing or there is a simpler way to do it?

Thanks for your answers

解决方案

typedef unsigned long bfield_t[ size_needed/sizeof(long) ];
// long because that's probably what your cpu is best at
// The size_needed should be evenly divisable by sizeof(long) or
// you could (sizeof(long)-1+size_needed)/sizeof(long) to force it to round up

Now, each long in a bfield_t can hold sizeof(long)*8 bits.

You can calculate the index of a needed big by:

bindex = index / (8 * sizeof(long) );

and your bit number by

b = index % (8 * sizeof(long) );

You can then look up the long you need and then mask out the bit you need from it.

result = my_field[bindex] & (1<<b);

or

result = 1 & (my_field[bindex]>>b); // if you prefer them to be in bit0

The first one may be faster on some cpus or may save you shifting back up of you need to perform operations between the same bit in multiple bit arrays. It also mirrors the setting and clearing of a bit in the field more closely than the second implemention. set:

my_field[bindex] |= 1<<b;

clear:

my_field[bindex] &= ~(1<<b);

You should remember that you can use bitwise operations on the longs that hold the fields and that's the same as the operations on the individual bits.

You'll probably also want to look into the ffs, fls, ffc, and flc functions if available. ffs should always be avaiable in strings.h. It's there just for this purpose -- a string of bits. Anyway, it is find first set and essentially:

int ffs(int x) {
    int c = 0;
    while (!(x&1) ) {
        c++;
        x>>=1;
    }
    return c; // except that it handles x = 0 differently
}

This is a common operation for processors to have an instruction for and your compiler will probably generate that instruction rather than calling a function like the one I wrote. x86 has an instruction for this, by the way. Oh, and ffsl and ffsll are the same function except take long and long long, respectively.

这篇关于如何定义和与位用C数组工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆