简体与繁体

2010-06-22 11:56

昨天看到一个帖子, 尝试用定量的角度来比较简体汉字和繁体汉字. 这个帖子专业性比较强, 就我的理解, 其主要逻辑是用字体的几何重心偏离方块的中心的程度来衡量字体的稳定性. 为了让这个概念更明确一点, 我们来举几个例子, 我们来看”旧”这个字:

旧这个字的字形相对简单点, 方便我们后面的计算. 上面这张图里, 灰色是选中字后的高亮效果, 我们也可以大概知道这个字是在一个什么样的正方形里. 对于这个字, 我们要考虑的是这个字的几何重心相对于这个灰色的正方形的偏移程度. 为了让你明白几何重心的原理, 我们来考虑一个更简单的情形. 由于旧这个字的字形比较特殊, 我们可以在研究的开始粗略地认为这个字是”田”字切掉左边三短横的结果. 现在我们来试图计算下面这个形状的几何重心:

这个形状是对于中间的虚线上下对称的, 因此这个图形的重心肯定在这条虚线上, 我们来看左右这个方向上重心的位置. 我们继续简单地假设上面这张图里面每条短线的重量是1, 长度也是1. 在前面我们已经说明, 重心肯定在中间的虚线上, 所以我们可以将这些短线的重量化归为中间虚线上的点的重量, 得到下面这样的图:

计算一条线上的点的重心是相对容易的:

(2*0 + 2*1 + 3*1.5+ 2*2)/(2+2+3+2) = 1.17

由于正方形的边长为2, 因此它的中心是(1, 1), 而我们计算得到的重心是(1.17, 1), 因此这个字就在x轴方向上偏移了17%.

上面费了不少笔墨, 只是向你解释原文中的中心及几何重心的概念, 以及偏离程度是怎么计算出来的. 当然, 虽然逻辑上每个重心都是要这么计算的, 但是原文要考虑的情形要复杂很多. 首先, 你可以回去看看前面贴出来的”旧”这个字的字形, 你首先会发现它左边那个竖和右边的距离比较短, 而且右边的”日”字下面还有些装饰性的出头. 而对于不同的字体, 面前说的距离和装饰线也许又有细微的区别, 而且可能线的宽度也会有区别(想想隶书). 因此, 原作者在计算几何重心时需要的工作量比我们这儿的粗略计算要大不少. 当然他所进行的计算都是用计算机完成的.

现在我来概括下原作者的工作: 原作者将道德经的某一段作为样本, 对于每个不同的字体, 计算了这一段样本的每个汉子的几何重心, 然后计算它相对于正方形中心的偏离程度, 然后对每个字体得到这样的一个平均值. 现在你可以看懂原文末尾给出的这些表了.

介绍完原文中的工作, 偶现在来评价下他的工作. 原贴说:

方正、中易等字体平均中心偏离正中,居左下角,标准差偏大(0.1左右)。类似中华民国教育部字标准楷书、黑
体-繁等字体,平均中心均为正中,标准差很小(0.05左右)。可见繁体字体的中心平稳度超过简体字体。

这个事实上是由于标点符号导致的。在中国大陆,标点符号比如逗号句号,都放置于左下角,而在香港、台湾等
地,标点符号位于字方中心位置。所以,港台的文字平稳性更好。这也是中国大陆书籍版面斑驳,每行有很强割裂
感的主要原因。 

所以,国家语委语言文字应用研究所《标点符号用法》课题组应该为用户的阅读困难和版面的斑驳付出责任。《国
家标准标点符号用法》起草人应该抓起来关着。

这一点实际上是比较没道理的. 首先, 港台的书籍很多都是竖排的, 因此, 繁体字中, 将标点符号放在字方中心位置是正常的, 而对于横排的字体, 将标点符号放在字方中心本身就是违背汉字从上到下从左到右的书写习惯的. 另外, 就我的个人观感, 读书这么多年从没感觉到简体字的排版有很强的割裂感(Word排出来的东西不论). 原作者在理性分析讨论后突然插入一句很没理性的话, 要把标点符号用法的起草人抓起来关着, 这让我感觉莫名突兀和不可理喻.

在作者去掉标点符号后, 重新计算了相关数据, 并比较了繁体汉字和简体汉字的差异, 他的结论是:

可以看到,对于相同的字体,改为繁体后,标准差亦有所减少,虽然减少的数值有限,其原因主要是因为很多汉字
的繁体和简体字形是相同。不过我们依然可以看到平均的标准差减小了 10%和15%左右。所以,说简化汉字破坏了
汉字的美观性,一点不错。当初鼓吹简化汉字的人都该拉出去砍了。

我个人认为, 这一点结论又太过主观了. 繁体字相对于简体字, 比划本来就多出不少, 在比划更多的情况下, 几何重心本身就是更偏向于中心的. 或者更宽泛一点说, 用几何中心相对于物理中心的偏离来衡量不同字体的稳定程度或许是合理的, 但是如果将繁体字拿来和简体字比较本身就是不合理的. 而将字体衬线, 间距等弃于不顾, 将字体的稳定程度等同于字体的美观程度就更没有逻辑性可言了. 至于原作者最后说的, “当初鼓吹简化汉字的人都该拉出去砍了”, 在我眼里就只是笑谈了.

最后扯点简体繁体的问题, 我对简体字毫无恶感, 正如我对繁体字毫无恶感一样. 如果在理性的框架下讨论简体繁体的问题, 我想我无论什么结论都会支持的. 但是我很难理解很多人都是从个人观感出发来讨论这个问题. 另外, 对于繁体字和文化传统上千丝万缕的联系, 我想这个问题更容易解决. 对于应该用繁体的场合, 例如史书, 古文, 诗词, 书法等, 当然应该使用繁体. 但是我想简体字的流行应该是很难阻挡的.

发表于 其它 分类. 1条评论

自定义python类方法实现加减比较操作

2010-06-19 11:34

最近在写一个组内项目, 需要把一群一群的类似字典的对象实现类似相加的逻辑. 为了让代码更好看逻辑性更强, 偶玩了下python的自定义类方法.

首先更详细地介绍下背景: 我们需要在Django中记录一个模型变化的历史, 我们有需求会将这个模型的某个实例的现在的状态和它的若干个变化历史相加. 为此, 我们用Django的序列化方法把这个实例导出成一个json字符串, 然后用这个字符串实例化一个类似字典的类. 变化历史的各种相加相减操作就是通过自定义这个类似字典的类的特殊的类方法而实现的.

既然这个类是用一个json字符串来实例化的, 我们简单地将这个类的名字定为Json, 其初始化方法类似:

class Json(object):
    """
    This class is used to hold a model instance's information.
    """
    def __init__(self, _json_string):
        """
        This class is initialized with a json formatted string.

        The json formatted string is provided using django's serialization
        tool, which accept a QuerySet or a list as an object. So here we have
        to retrieve the first(and the only) object in the list.
        """
        self.init_string = _json_string
        _dictionary = json.loads(_json_string)[0]
        self.model = _dictionary['model']
        self.object_id = self.pk = _dictionary['pk']
        self.fields = _dictionary['fields']

看起来很长一段代码, 实际上只是定义了若干基本类属性而已. 这些属性包括初始化字符串, 被序列化的实例的模型和主键, 以及一个存放原实例的属性的self.fields字典. 如果对这些名字不太熟悉可以自行去围观下django的序列化工具的json输出, 这个页面上有例子.

Json这个类只是存放了类的序列化的内容, 为了记录历史, 我们需要将两个这样的类相减以得出变化. 在定义相减这个操作之前, 我们需要定义一个用来存放历史变化的类:

class Jsondiff(object):
    """
    This object is used to save substraction results from two Json objects.
    """
    def __init__(self, _diffdict):
        """
        Input format specification
        --------------------

        the input json string represents a dictionary of differences. Like:
            {
                'fieldname': (newvalue, oldvalue),
            }
        It also contains a special field named '_model', containing the name of
        the model and the id of the object.
        A realworld example is provided below:
            {
                u'_object': (u'gsdb.server', 1),
                u'tag': (u'12535', u'12537'),
            }
        """
        self.fields = _diffdict
        self.model = self.fields['_object'][0]
        self.object_id = self.fields['_object'][1]
        del self.fields['_object']

同样的, 看上去很长的代码只是干了很有限的几件事情: 从类初始化参数中拿到实例的模型和主键, 作为类属性保存起来, 并从初始化参数中删除这个用于存放元信息的特殊键值, 这样我们再后面进行各种操作时就不需要再讨论这个特殊的键值了.

OK, 两个类已经定义完了, 我们开始定义一些特殊的类方法. 首先, 我们需要定义一个方法能够比较两个Json实例的区别以得到一个Jsondiff实例. 我们需要实现下面的代码:

jsondiff0 = json1 - json2

为此, 我们需要自定义Json的__sub__方法:

    def __sub__(self, _json):
        """
        This method would substract two Json objects and give a Jsondiff
        object.

        The object represented by _json is the old object, 'new - old' would
        make more sense than 'old - new'.
        """
        _diffdict = {
            '_object': (self.model, self.object_id),
        }
        for _field in self.fields:
            if self.fields[_field] != _json.fields[_field]:
                _diffdict[_field] = (self.fields[_field], _json.fields[_field])
        return Jsondiff(_diffdict)

这段代码很容易理解. 你不是要比较两个Json对象吗? 既然所有相关的值都在self.fields里面, 那我们就一个个地进行比较, 如果有不同的地方就按照一个预设的格式记录下来. 我们这儿将这些记录放到一个字典里面, 处理完每个键后就直接将这个字典作为初始化Jsondiff类的参数实例化一个Jsondiff对象, 然后就可以直接返回这个对象了. 到这儿, 我们已经实现了前面写的json对象相减的代码. 下一步, 既然已经写了减法, 不写加法就不合理了:

# Since we can do:
jsondiff0 = json1 - json2
# we wanna have this, too:
json1 = json2 + jsondiff0

好吧, 我们现在来定义加法:

    def __add__(self, _jsondiff):
        """
        This method would add a Json to a Jsondiff object.
        """
        _sum = copy.deepcopy(self)
        for _field in _jsondiff.fields:
            _new, _old = _jsondiff.fields[_field]
            if _sum.fields[_field] != _old:
                raise RuntimeError
            else:
                _sum.fields[_field] = _new
        return _sum

此处, 为了避免执行加法后改变已有实例的属性, 我们用deepcopy将原来的Json对象复制了一份. 然后从Jsondiff里面读键值, 对于每个键值看看diff里的内容和当前的实例的属性有没有冲突, 以确定我们要进行的操作是不是合法的. 如果一切都没问题, 返回一个Json对象.

为了让这一切更和谐, 我们还定义了一个Jsondiff的__add__方法, 这样我们哪天把前后顺序弄反了也不会有多大的事情:

    def __add__(self, _json):
        """
        This method would add a Jsondiff to a Json object.
        """
        return _json + self

有了这段代码, 我们在进行Json对象和Jsondiff对象的加法时可以肆无忌惮地将Jsondiff放在前面或者后面了. 而如果没有这个对象, 我们只能老老实实地将Jsondiff放在后面.

后来在使用中, 我发现我经常会需要比较两个Json对象的创建时间来比较哪个更新一点. 为了简化这些操作, 我给Json对象添加了一个date属性, 记录原模型的修改时间. 这样我每次只需要比较Json对象的date属性即可. 既然已经有了这个属性, 我们可以更进一步的定义__cmp__方法来使Json对象的比较更美观更和谐:

    def __cmp__(self, _json):
        """
        This method would compare two Json object's date.
        """
        return cmp(self.date, _json.date)

定义了这个方法后, 我们能做类型下面的操作:

>>> json1 > json2
True

标签:, 发表于 Python开发 分类. 发表评论

张悟本

2010-06-03 10:22

事件回放下:

  1. 春节在家时, 家里的若干个阿姨和偶妈都追着让我给她们下载张悟本的视频. 我这个几年没看电视的人围观了下, 觉得这丫的基本就是在扯. 不过反正不是我要看, 也就顺手下载了一把.
  2. 前几天打电话回家, 说起绿豆涨价, 偶妈跟我说张悟本是骗子, 说他导致了绿豆涨价. 我囧…
  3. 今天网上看到一篇文章说是电视台编导的错, 为了经济利益而纵容了这种骗子上台.

关于这个话题, 随便扯几句吧.

中医我一向不信的, 这种没有理论的验方虽然可能是对99%的人有效, 但是你没法保证那1%的不幸不会发生在你的身上. 相比之下, 我更愿意相信我可以理解的西医. 所以, 当一个中医的专家站上台讲座的时候, 下面坐着的我给他的起评分就已经不及格了.

话说这个张某某扯的话比较多, 我现在也懒得去找他的视频来玩找错误的游戏了, 说两个我印象比较深的例子吧.

张某某说某金属(好像是锌吧?)是抗癌的. 国内一直不同意, 直到十几年后, 才有美国科学家发表学术论文说锌是抗癌的. 这句话我当时看了就觉得很不爽. 首先, 锌的存在方式就没说清楚, 具体是耦合在蛋白质里的锌还是呈离子状态的锌? 耦合在蛋白质里的锌是和哪种或者哪类蛋白质耦合的? 耦合后的蛋白质的构型是什么样子的? 这种蛋白质以什么机理阻止癌细胞的增生或者杀灭癌细胞? 如果是离子状态的锌, 这些锌是什么价态的? 以什么方式参与了哪些生化反应? 这些都没有回答. 接下来, 我本也不指望你这个骗子能够答出我之前说过的问题, 那么, 您能从中医的角度解释一下为什么这些锌能够抗癌吗? 哦, 您一笔带过了, 难怪难怪. 我们继续来研讨一下所谓的抗癌的问题. 癌症种类那么多, 这玩意能够包治百病? 不是吧? 那锌岂不是要变成贵金属? 而抗, 又是一个太过笼统的提法, 锌是能够阻止癌细胞增生呢, 还是能够防止它扩散啊? 是能够治愈病人呢还是能够延长其生存时间啊? 如果这些都能说是抗. 那么我们可以把话说得极端一点, 你每天多吃点肉都能够增强体制, 那是不是说脂肪和蛋白质也是抗癌的? 再往后, 您十几年前说锌能抗癌, 之后十几年间都没有科学家说锌能抗癌了. 这个我还真不信. 那么多为了毕业可以舍身取义的硕士生博士生, 为了科研基金可以寝食不休的讲师教授都在孜孜不倦的堆论文, 这么多年来都没有一个人能够说锌能够在某种环境下对某种癌细胞在实验用小鼠体内的增生产生抑制作用? 这个几率我相信比中五百万要小太多了. 你说最近才有美国科学家发表论文说锌能抗癌. 那是你见得太少了吧!

张某某说, 自然界有白天和黑夜的原因是, 白天是给你工作的, 晚上就该睡觉. 这句话让我想起了Sheldon的一句台词, “This party is a scathing indictment of the American education system.” 从张某某的这句话, 我可以批评他不懂简单的物理学和天文学, 对生物多样性和生物进化没有基本的认识, 甚至从文科的角度, 在逻辑学上这句话也是说不通的. 不过我不打算细说了. 如果我给了这么多线索还不知道我想说什么的话, 那么这篇文章也不是写给你看的.

关于张某某的就扯这么多, 在这个人身上浪费笔墨时间实在不值得. 接下来说绿豆涨价. 绿豆涨价只是一个典型的例子, 用来说明最近普遍出现的粮食作物价格上涨. 而要说如果有一个节目的播出能够导致物价的普遍上涨, 那么这个节目只能是新闻联播. 至于这些乱七八糟的养生杂谈连资格证都拿不到. 至于到底谁开始说张某某导致了绿豆价格上涨, 我不知道, 也不高兴去了解. 虽然对他来说是冤枉的, 但是偶从不可怜骗子.

接下来是媒体在这件事中所起的作用. 前面说的我刚看的那篇博客说这是电视台编导的错. 那我还真不开心了. 电视台编导有啥错? 就因为没对这个骗子加以审核? 搞笑! 电视台编导当然要拉这种人上电视了! 有亲和力, 有感染力, 说起话来头头是道. 吸引中老年妇女提高收视率最合适了. 这种人不上电视那是犯罪. 你说张某某是骗子, 不能这样上电视, 这样不好? 笑话, 每天我们遇到的骗子还少? 随随便便走在路上有, 不出门宅在家里还有人给你发中奖短信, 关了手机上网又会看到一堆, 看报纸? 别逗了, 报纸上的骗子更多了. 要彻底杜绝骗子, 要么你从此长闭双眼, 两耳不闻窗外事, 一心只在周公; 要么你学会了解事物的本质, 睁大眼睛. 而首先, 就是要受教育水平的提高. 至于这一点是谁的责任, 我也就不多说了.

标签: 发表于 其它 分类. 发表评论