问题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%。真是很令人惊讶的速率!

 

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

NOI题解(1.6编程基础之一维数组)(补全)

01:与指定数字相同的数的个数 #include "iostream" using namespace std; int main() { int count; int time=0;...
  • v_xchen_v
  • v_xchen_v
  • 2016年09月07日 19:00
  • 2125

具体问题具体分析

小明和小强都是张老师的学生,张老师的生日是M月N日,2人都知道张老师的生日 是下列10组中的一天,张老师把M值告诉了小明,把N值告诉了小强,张老师问他们知道他的生日是那一天吗? 3月4日 3月5日...
  • piaoboyijianke1
  • piaoboyijianke1
  • 2013年03月16日 09:33
  • 419

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

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

SVN由1.6更新到1.8后出现问题

org.apache.subversion.javahl.ClientException: The working copy needs to be upgraded svn: Working co...
  • vba_2001
  • vba_2001
  • 2012年03月21日 12:47
  • 1025

陶行知:学生自治问题之研究

偶尔看到陶行知先生在五四时期写的一篇文章,谈学生自治。想着当下校园中的一些事情,还是可以给我们很多启示的。其中的期望,不仅是校方能够给学生多少自主,更在乎学生在现有框架下是否抓住了可以把握的自主,让旁...
  • sxhelijian
  • sxhelijian
  • 2013年11月21日 09:06
  • 4856

kubernetes 1.6高可用集群在部署中遇到的问题

Failed to start LSB: Bring up/down networking. 由于在创建vmware虚拟机时使用了克隆的方式,造成MAC地址改变。 解决方法: 通过命令 ip...
  • wenwst
  • wenwst
  • 2017年06月16日 18:37
  • 436

用 Quartz 进行作业调度--在quartz-1.6.0下调试通过

http://www.ibm.com/developerworks/cn/java/j-quartz/index.html#N10096 ...
  • fuyangchang
  • fuyangchang
  • 2007年07月03日 12:54
  • 2567

7-13(图) 畅通工程之局部最小花费问题(35 分) 35分代码

最小生成树 克鲁斯卡尔算法 首先要将已经修建的道路进行并查集合并操作 用 set 存集合中结点的个数,,剩余的点按照基本操作进行就好了 (注:博客作为交流使用,切勿抄袭应付作业) ...
  • xiang_6
  • xiang_6
  • 2017年10月04日 16:08
  • 309

maven报错 Dynamic Web Module 3.0 requires Java 1.6 or newer 解决

转自:http://qussay.com/2013/09/13/solving-dynamic-web-module-3-0-requires-java-1-6-or-newer-in-maven-p...
  • ch717828
  • ch717828
  • 2015年07月23日 13:41
  • 782

PTA-数据结构 5-50 畅通工程之局部最小花费问题 (35分)

某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。...
  • flx413
  • flx413
  • 2016年11月29日 00:33
  • 574
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:问题1.6之具体问题具体分析
举报原因:
原因补充:

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