位运算实现int的abs/min/max函数

论坛上两次看到不用比较计算最大/最小值了,第一次讨论时有个人有人给出了最理想的答案。那个人说在做图像运算时,比较运算会对指令流水线效率有较大影响,因而需要另外的实现。第二次讨论时找不到第一次的帖子了,于是凭着印象并查了一些资料,仔细想了想,得到了之前的答案(假定int为4个字节):

int min(int a, int b)

{

int diff = b – a;

// b < a: a + (diff & -1)

// b > a: a + (diff & 0)

return a + (diff & (diff >> 31));

}

int max(int a, int b)

{

int diff = b – a;

// b < a: b – (diff & -1)

// b > a: b – (diff & 0)

return b – (diff & (diff >> 31));

}

int abs(int a)

{

int temp = (a >> 31);

return (a + temp) ^ temp;

}

原理上主要有两点:

1, 整数是以补码表示的

2, 有符号数的移位运算是算数移位(乘2和除2)而非物理移位

正数和0的补码同原码,负数的补码是绝对值的反码加1。-1的补码表示是0xFFFFFFFF。

任何一个非负整数(0~231-1)右移31位都是0;任何一个负整数(-231~-1)右移31位都是-1。这样min和max就比较容易理解了。

再看abs

a ^ -1 == ~a-1

a ^ 0 == a

若a非负,没有任何变化;若a为负,加-1再取反,得到绝对值。

VS下文本编码探索——成功就在再坚持一分钟!!

前就写了文件分割器,经过了各种优化后,感觉不错,那时我就想写一个文本分割器,但是由于对字符编码的不熟悉,所以迟迟没有开工。

最近学习win32编程,虽然老师是在VC6.0下面教授内容,但是因为之前有过自学,加上其它种种原因,我一直就在VS2008下编写。在VS2008下默认使用Unicode字符集(当然,其实是可以使用第二个选项的多字节字符集)。

昨天回去后查了一些资料终于解决了在_wfopen函数打开Unicode文本时,输出到终端和输出到文本里乱码的问题,有了这个基础后,今天我就打算花费一点时间去写一个分割Unicode编码的文本的文本分割器。

悲剧啊,上午搞了3个小时结果输出到文件中时还是有乱码。下午我问了老师,老师说要用二进制方式打开文本。我一试,还是不行,但是我发现我对二进制和文本方式打开文件的不同点不能很清楚的分别,又翻了一会儿书。

又重新分析上午的代码,我用UltraEdit以16进制方式打开分割后的文本,发现乱码的文件没有开头FFFE,但是以文本方式打开时,虽然会自动加入FFFE,但是内容仍然乱码。

于是我尝试认为的加入FFFE,关键的部分来了,我是以FFFE的顺序写入到文本,然后运行程序:

毫无头绪的错误。经过跟踪发现是在fwrite时出错了,我百思不得其解。后来无意中用记事本查看文本编码时,才发现问题:

而正常的状况时,应该是小端法存储数据的(如下图),现在再看上图的错误,其实系统已经告诉我了错误原因了。

于是我已FEFF的顺序写入文本。见证奇迹的时刻到来了,

总结:通过今天的问题,我发现,虽然我之前知道X86架构的cpu是采用小端法存储数据,但是我们在一些常见的编辑器中看到的数据已经是编辑器转换成人类熟悉的格式了,所以当我尝试去直接操控这些数据的存储时,必须采用原始的机器识别的方式。

关于ncursesw的一点总结

前几天是重新安装的一个Kubuntu,在里面直接搜索软件仓库,安装libncursesw5-dev …………,这在上一篇博客上已经写了。今天我去吃晚饭时,一想有点不对劲,回来后又打开之前的虚拟机(这个虚拟机中我之前下载了ncurses的源码,经过手动编译安装成功)尝试编译时带 -lcursesw参数,编译通过没有问题,我find include目录,有cursesw.h文件,所以我有打开代码在里面加上了setlocale(LC_ALL, “”);编译后运行,不知道应该是称之为幸运还是不幸,正常显示中文了!

浪费我周四晚大半夜的努力啊,嗨!!!

捉迷藏之ncurses

今天把电脑主机临时搬回了学校宿舍,上网查了如何配置ncurses,才能让你出入ncurses支持宽字符。

前上网查过很多次,都没有什么结果。今天晚上又在虚拟机安装了kubuntu10.10, 后来又安装kde,弄到12点才差不多将kubuntu的界面,语言更新好。

然后开始艰巨的配置ncurses的任务了。之前就写了一个Linux下终端里使用的基于tcp的聊天室,但是一直感觉输入输出在一个窗口很不爽,上网一查才知道有curses这么一个库。后来自己下了一个ncurses的二进制文件,但当时不知道如何安装,今天下午看了INSTALL文件里的说明,才发现其实很简单。安装了当时输出UTF-8编码的汉字时仍有部分乱码,实在没办法了,所以留着网上回学校研究。

安装了kubuntu后,在“软件管理”中发现了系统已经安装了ncurses,于是我就写了个example试试,但是提示找不到ncurses.h文件,于是我就用啊apt-get安装了ncurses,编译通过,能够正常输出,但是人不能正确输出UTF-8编码的文件。于是我对照“软件管理”中已安装的ncurses的内容选择了libncursesw5-dev安装(如下截图)

但是编译通过后仍是不能正确输出,我想起网上有一个设置语句:setlocale(LC_ALL, “”);

再次编译,运行。

 

OK!终于能够正常的输出中文了。