EverET.org

好记性不如烂笔头

判断两个有符号整数相加是否溢出

| Comments

在Python,默认的整数是long型的,也就是机器字长,32位的最大有符号整数为0x7fffffff,64位最大有符号整数为0x7fffffffffffffff。

而在Python,支持任意大整数的运算,也就是,当我们的long型整数(在Python对象中type为int)溢出的时候,Python会自动将其变成大整数(在Python对象中type为long),也就是和Java中的BigInteger一样,支持任意位数的整数计算,不过更加方便。

我的系统是64位的,最大符号整数为0x7fffffffffffffff,我们来看看两个0x7fffffffffffffff相加会发生什么事情。

Python使用spark模块构造计算器

| Comments

Spark简介

Spark 解析器与 EBNF 语法有一些共同之处,但它将解析/处理过程分成了比传统的 EBNF 语法所允许的更小的组件。Spark 的优点在于,它对整个过程中每一步操作的控制都进行了微调,还提供了将定制代码插入到过程中的能力。

Spark的最新版是10年前发布的,真是非常的长寿,可见设计精良。其中的采用的设计模式有Reflection Pattern、Visitor Pattern、Pipes and Filters Pattern和Strategy Pattern。

初识Spark

第一次知道Spark这个模块是在IBM的网站[3]上看到的。

第一次激起我学习这个模块的兴趣是在看Python源码的时候,发现Python的编译器是用The Zephyr Abstract Syntax Description Language(Parser/Python.asdl)来定义的语法,然后通过(Parser/asdl.py、Parser/asdl_c.py、Parser/spark.py)根据Parser/Python.asdl生成C语言解析器。其中仅用了1000多行就实现了一个yacc。这个是非常地强大。

用LL(1)递归下降语法器构造一个计算器

| Comments

LL(1)

何为LL(1)?通俗来说就是向前看一个词法单元的自顶向下解析器。两个L都代表left-to-right,第一个L表示解析器按“从左到右”的顺序解析输入内容;第二个L表示下降解析时也是按“从左到右”的顺序遍历子节点。而(1)表示它使用一个向前看 词法单元。

我们从一个简单的计算器来看看递归下降的语法器如何构造。

对于 2 + 3 * 5 的抽象语法树如下:

构建LL(1)递归下降语法解析器

| Comments

不管什么语言应用,识别语言这一步都很重要。

在小学时,大家都学习过如何分辨句子中的不同语言成分,例如动词和名词等。识别计算机语言也是如此(我们称之为语法分析)。

小例子

我们来看一下:

return x + 1;

语法图:

我喜欢的那些书

| Comments

C/C++

深度搜索C++对象模型

讲述了C++背后许多鲜为人知的东西。看完后或许会对C++的对象模型有所感慨。

STL源码剖析

STL的设计思想非常值得学习。像内存池和各种通用的接口等思想都要细细品味。

C专家编程

有很多好的技巧。

Effective C++

Python根据图片生成字符画

| Comments

字符画很好玩,我们来看看怎样将一张图片变成字符画。

我们首先将图片变成黑白的,那么每个像素的取值范围为:0-255.

然后我们将0-255映射到0-14的范围上,然后用如下字符代替:

color = ‘MNHQ$OC?7>!:–;.’

也就是像素为0的点用“M”表示,像素为14的点用“.”表示。

原理非常的简单,我们用Python来编写的话也非常的简单。只要借助PIL,就可以很轻松地在Python中处理图像。

我们来看一段代码:

猜想祖国的伟大的围墙的原理

| Comments

防民之口,甚于防川。

引用自百度百科的对于“防民之口,甚于防川”的启示:

中国历史上有很多统治者荒淫无道,但他们又怕人民议论,就采取了压制社会言论的措施,以为可以高枕无忧、平安无事。实际上这是最愚蠢的作法,它不仅使下情无法上达,错误的政策得不到纠正,加剧社会矛盾。更可怕的在于虽然民众口上不说,但心里却充满了仇恨,只要社会矛盾到达临界点,大规模的暴乱必然爆发,给社会生产力造成极大破坏。正可谓“防民之口,甚于防川。”中国人是世界上最能忍受暴政的民族,但也是爆发起义最多的国家。

无逻辑的舆论的控制,究竟会引发什么后果呢?或许多年后答案便自己浮现。

暂且不谈论我们伟大的围墙的对于人民生活的影响,我们来看看它的技术方面的实现。

在Ubuntu下编译调试版的Python

| Comments

在Windows调试Python解释器还是非常方便的,因为有强大的VS。

不过在Linux下可能有点不那么顺畅。但是稍微设置一下还是可以很方便地调试的。我们来看看在Ubuntu下怎么做。

获取源码

在Ubuntu下获取Python2.7的源码非常方便,只需要使用apt-get就可以轻松取得。在Shell下输入

apt-get source python2.7

即可以将Python的源码下载到当前目录。

然后我们就可以得到一个tar.gz的压缩包。

编译

我们进入源码文件夹后输入

1
2
./configure
make

然后就可以编译得到python。

当然,此时的Python不是调试版的,如果要编译调试版的Python,就需要再做一些东西。首先我们可以Google一下怎么做,貌似很多都是引用了源码README的一段话:

C++与Python混合编程

| Comments

混合语言策略可以汲取各语言之所长,让开发更加敏捷。混合语言策略在在应用得当时可以让程序更加优雅。

在《Unix编程艺术》中,Raymond说道:

混合语言是一种知识密集型(而不是编码密集型)的编程。要让它能够工作,我们不仅应该具备相当数量的多种语言应用知识,并且还需要具备能够判断这些语言在什么地方最适合、以及怎样把他们组合在一起的潜经验。

在混合语言编程中,我们遇到的第一个问题是如何需要让他们可以互相调用。也就是像C++可以调用Python的函数、Python又可以调用C++的函数。

对于C++和Python的混合编程主要有两种方式。

  1. 将C++写的模块编译成动态链接库,然后由Python主程序使用。这种一般是单方向的使用。

  2. 用C++主程序调用Python。然后Python中可以使用C++主程序的函数。

对于第一种方式非常简单,我们在此就不讨论了。我们将着重讨论第二种方式。