问题1.6之具体问题具体分析

原创 2011年08月04日 18:49:20

题目是:你会如何使用位逻辑运算实现位向量。


        看到这个题目心里感到十分迷茫,实现位向量为何要用逻辑运算呢?于是就随手敲下了第一版的代码


//GbitVector1.h
#define MAX_VECTORS1 20000
bool vec[MAX_VECTORS1];
void set(int index)
{
	vec[index]|=1;
}
void clear(int index)
{
	vec[index]&=0;
}
bool beSeted(int index)
{
	return vec[index];
}

        这里使用位运算的地方实在是无聊,直接赋值就可以。于是我看了答案,答案中并不是以bool数组作为存储数据的原始数据结构,而用地是int数组。有了新的思路,当然就有了新的代码


#define MAX_VECTORS2 625//  20000/32
int vec[MAX_VECTORS2];
void set(int index)
{
	int interIndex=index>>5;//索引到哪一组BIT
	int realIndex=(index-interIndex<<5);//索引到一组BIT中的哪一个
	vec[interIndex]|=1<<realIndex;
}
void clear(int index)
{
	int interIndex=index>>5;
	vec[interIndex]&=1<<(index-interIndex<<5);
}
bool beSeted(int index)
{
	int interIndex=index>>5;
	return vec[interIndex]&(1<<(index-interIndex<<5));
}

        这一段代码比较复杂的地方就是如何根据提供的索引找到其真正的存储的位置。比如我要设置第65个地方的向量为1,我只能先找出我在第几个int中存储了这个向量的位置:65/32=2;用位运算就是65>>5=2.再找到这个int中第几位正好表示了这个向量:也就是65%32=1;用位运算就是:65-2<<5=1.所以65这个地方在内存中int数组的2位置,在该位置0-32共32位中的1位。这里每次置位需要3个位移操作,1次减法,1次逻辑运算。

        在看过答案之后,发现有在65%32这一步有更简洁的写法,因为是对32取模,本质就是取出某个数字所有后八位的全部信息。所以有如下代码片段.其中的0x1f相当于取出后八位数字的掩码。


void set(int index) 
{ 
vec [index>>5] |= (1<<(index & 0x1F)); 
}

        这里每次置位只需要2次位移2次逻辑运算

        如果没有要求,暂时认为第一种用bool的方式是最简便最快捷的。

        如果是因为种种原因不能使用bool类型,那么第二段代码是应该可以写出的.至于第三段代码,需要对具体的问题进行分析才可以优化得到。虽然这个问题的本质算法没有改变,但是由于具体问题的特殊性,可以对代码进行适当的优化计算。

 

        突然想到原来见到的一段很是流行的求方根的代码


float InvSqrt (float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i >> 1); // 我只知道5f是什么意思,后面的呢?
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x); // 这是普通的迭代
return x;
}

        这段代码使用的是牛顿迭代法,但是它只进行了一步的迭代就得到了很准确的数值。为什么呢?

        1.他通过类型装换,将本应该是float类型的数据,转换到int类型,并使用int类型的快捷的运算

        2.他提供了一个数字0x5f3759df作为整个牛顿迭代的起点,也就是说,虽然从理论上讲,用牛顿迭代法可以从任意位置开始,进行任意多次迭代,但是如果使用0x5f3759df这个数字,只用一次迭代,就可以获得很好的效果。这个算法比微软库中的sqrt快了20%。

        故事到现在还没有结束,因为这不是最好的,这段代码可以利用空间换时间的方式,所有计算通过查表进行,这样可以再把速度提高100%。真是很令人惊讶的速率!

 

        自古有言“熟能生巧”,这是不错的,在实践中,多思考,即使不能从本质上对问题的解决方案有一个突破,也能在具体的细节上逐步优化改良,渐渐臻于化境。

相关文章推荐

具体问题具体分析

  • 2011年12月22日 13:28
  • 25KB
  • 下载

具体问题具体分析 之 Q&A票

前言:             今天在做NK认证基盘测试时,发现了一个暗号话异常的故障。     同时,在証跡中把问题产生的原因描述了一下,但是在描述这个问题时, 暴露了一些问题,这些问题...
  • sxzlc
  • sxzlc
  • 2011年12月09日 23:42
  • 1029

不良资产催收 具体问题具体分析

催收作为逾期不良资产的方式之一,在实际工作中会遇见很多困难,催收工作是一项复杂且需要工作人员耐心细致,所以在催收时,往往要根据企业的逾期情况的不同来采取不同的策略,下面我们来一一介绍。       ...

数据库系统具体问题讲解

  • 2008年11月21日 19:23
  • 735KB
  • 下载

UDP主要丢包原因及具体问题分析

UDP主要丢包原因及具体问题分析   一、主要丢包原因   1、接收端处理时间过长导致丢包:调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法...

[整理]ubuntu10.10编译TQ2440的x86-qtopia-2.2.0具体问题总结及原因分析

声明:转载请注明出处。 Briefly, the shell commands `./configure; make; make install' should configure, build,...

PL/SQL 基础---具体问题分析

PL/SQL 基础—具体问题分析 主要讨论PL/SQL中一些典型问题和解决思路; 1.排序问题假设有以下数据:    LINE_NUMCODEDESCRIPTIONNEW_ORDER 11B2...
  • villare
  • villare
  • 2016年12月07日 13:35
  • 177

UDP之丢包原因及具体问题分析

之前一直没考虑清楚为何接收到UDP数据丢包的问题,当意识到这造成很大问题时便狂查资料,有以下结论: 1.发送方发送的数据太快,导致UDP输入队列溢出(系统会丢掉一些包),在应用程序看来是即是丢包...

UDP主要丢包原因及具体问题分析

文章来源:http://www.2cto.com/net/201311/254835.html UDP主要丢包原因及具体问题分析   一、主要丢包原因   1、接收端处理时间过长导致丢包:...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:问题1.6之具体问题具体分析
举报原因:
原因补充:

(最多只允许输入30个字)