KEEP K.I.S.S.

tk's blog

"a <= b" 和 "not ( b > a)"

今天在看《LUA程序设计(第2版)》时候,发现了一个比较有意思的问题。

在 13.2 节 关系类的元方法 中,作者解释道为什么要同时提供 小于小于等于 两个关系运算符的实现:

在 Lua 4.0 之前,所有顺序操作符(order operators)都被转化为一种操作符(小于),例如,a <= b 转化为 not (b < a)。不过,这种转化遇到“部分有序(partial order)”就会发生错误。所谓“部分有序”是指,对于一种类型而言,并不是所有的值都能排序的。例如,大多数计算机中的浮点数就不是完全可以排序的。因为存在着一种叫 “Not a Number (NaN)”的值。 IEEE 754 是一份当前所有浮点数硬件都采用的事实标准,其中将 NaN 视为一种未定义的值,例如 0/0 的结果就是 NaN。标准规定了任何涉及 NaN 的比较都应返回 false(假)。这意味着 NaN <= x 永远为假,但是 x < NaN 也为假。因此,前面提到的将 a <= b 转化为 not ( b < a ) 就不合法了。

就是说 关系运算符的结果并非都是真的表示两个运算数是可以比较的,例如 在 IEEE 754 标准中提到,所有涉及 NaN 的浮点数关系比较全部应返回 false,也就是说 NaN <= x 为 false,NaN > x 也为 false,所以 a <= b 和 not ( b > a) 并非完全等价。

另外一段叙述是针对扩展使用的

在上面的集合示例中,也存在着类似的问题。在集合操作中 <= 通常表示集合间的包含关系: a <= b 通常意味着 a 是 b 的一个子集。根据这样的表示,仍有可能得到 a <= b 和 b < a 同时为假的情况。因此需要分别为 __le(小于等于)和 __lt(小于)提供实现

这里举例,a、b 两个集合交集为空,并集不为空,则 a <= b 为假,而 b > a 也为假。

对于断言 ASSERT 的理解

昨天看了《代码大全》的“防御式编程”章节,解惑了长期以来自己对于断言的理解。

书中给了使用断言的指导意见,如下

  1. 用错误处理代码来处理预期会发生的状况,用断言来处理绝不应该发生的状况。
  2. 避免把需要执行的代码放到断言中
  3. 用断言来注解并验证前条件和后条件
  4. 对于高健壮性的代码,应该先使用断言再处理错误
其中有一段话,很清晰地说出了断言的典型使用情况:
对来源于内部系统的可靠的数据使用断言,而不要对外部不可靠的数据使用断言,对于外部不可靠数据,应该使用错误处理代码。断言可以看成可执行的注释。
系统外部的数据(用户输入,文件,网络读取等等)都是不可信的,需要严格检查(通常是错误处理)才能放行到系统内部,这相当于一个守卫。而对于系统内部的交互(比如子程序调用),如果每次也都去处理输入的数据,也就相当于系统没有可信的边界了,会让代码变的臃肿复杂;而事实上,在系统内部,传递给子程序预期的恰当数据应该是调用者的责任,系统内的调用者应该确保传递给子程序的数据是恰当可以正常工作的。这样一来,就隔离了不可靠的外部环境和可靠的系统内部环境,降低复杂度。
 
但是在开发阶段,代码极可能包含缺陷,也许是处理外部数据的程序考虑的不够周全,也许是调用系统内部子程序的代码存在错误,造成子程序调用失败。这个时候,断言就可以发挥作用,用来确诊到底是那部分出现了问题而导致子程序调用失败。在清理了所有缺陷之后,内外有别的信用体系就建立起来。等到发行版时候,这些断言就应该没有存在必要。
 
附一个C++可以用的自定义断言
#ifndef _ASSERT_EX_H
#define _ASSERT_EX_H

#include <stdlib.h>
#include <stdio.h>

#ifdef _DEBUG
#define _ASSERT(exp, message) { \
if (!(exp)) {		\
        fprintf(stdout, "Assertion failed: \"%s\"\nMessage: \"%s\"\nline: %d\nfile: \"%s\"\n", \
                #exp, message, __LINE__, __FILE__); \
	exit(EXIT_FAILURE);						\
	 }     \
}
#else
#define _ASSERT(exp, message)
#endif

#endif //_ASSERT_EX_H
 

四参数转换使用的公式

设四参数转换 尺度 为 $k$,旋转角为$\theta$,坐标系位移量分别为$\Delta X$$\Delta Y$则单点转换公式为

\begin{bmatrix} X_1\\Y_1  \end{bmatrix} = \begin{bmatrix} \Delta X\\ \Delta Y  \end{bmatrix} +  \begin{bmatrix} k \cdot \cos\theta & - k \cdot \sin\theta \\ k \cdot \sin\theta & k \cdot \cos\theta \end{bmatrix} \begin{bmatrix} X_0\\Y_0  \end{bmatrix}

变换后的矩阵形式为

\begin{bmatrix}  1&0  & X_0 &-Y_0 \\   0&1  &Y_0  & X_0 \end{bmatrix} \begin{bmatrix} \Delta X \\ \Delta Y \\ k \cdot \cos\theta \\ k \cdot \sin\theta \end{bmatrix} = \begin{bmatrix}  X_1 \\ Y_1 \end{bmatrix}

这就是类似 \[BX=A\] 的平差式

所以可知

        \[X=\bigl(B^TB\bigr)^{-1}B^TA\]

 

PS:实验下学 \LaTeX{} 怎么写公式

命令行、脚本化、自动化以及其他

昨晚一个同学问了我一个问题,他跟着导师做项目,问为什么以及怎么去解析特定样式的命令行参数,比如

./DT -r rrr.txt -t ttt.txt -p 0 -s 5 

这里明显是为了脚本化和自动化用的,具体解析就不讲了,其实命令行参数设置可以参考 GNU 风格,比如上面的这个就可以写作

./DT -r,rrr.txt -t,ttt.txt -p,0 -s,5 

GNU 风格的好处在于明辨,参数项和参数值在同一个字符串中,用逗号分隔,进行解析时候就简便一些。命令行的函数好处在于便于使用管道(PIPE)和脚本来实现自动化,避免低效的手工和重复。

这段时间自己在看《程序员修炼之道》,非常好的一本书,感觉到自己有好多的不足,至少从怎么做一个卓有成效的程序员,来讲,我并没有明显的使用脚本去自动化去做一些事情,总是依赖GUI和手工。。。。

其实讲的很多内容并不是局限在编程这个领域,书中也是这么说的,学以致用,卓有成效的手段在各个领域都会有所用处。看来自己还是得不断努力了,不要再愚昧愚蠢的手工重复。。。。。

此书强烈推荐。

 

KDE下Qt程序字体问题

 

弄了几天的问题,终于算是部分解决了。

问题是这样的,在KDE下,并不是所有程序的字体都和KDE设置的是一样的,就连基于Qt的程序也是如此。之前下载了 Qt SDK 1.1.3,自带的Qt Creator 的字体看上去太蛋疼了,模糊,又不好看,怎么设置也没办法弄。

后来在网上找了很多方法,qtconfig 也试过,没有效果,有人质疑 Qt 程序的字体设置和 KDE 默认的冲突,但是也没有找到解决方法。

没办法,最后找到了一个设置微软雅黑字体的办法来试试,结果还是不错的。

在用户目录下有个字体设置文件, .fonts.conf ,就是修改这个文件来修改全局字体。如下所附带的就是一个用于微软雅黑显示所用的代码。其实不知道还有没有更好的办法,因为这样设置后Chrome里的字体也全部微软雅黑了。。。。。。 等学会了 这个文件的原理就能找到好方法了吧。。

 

================= 9/22 更新 ==============

新配置文件,完全去除windows宋体,建议不使用该字体。新配置文件为 /etc/fonts/local.conf 没有可以新建。

 

<?xml version='1.0'?>
<fontconfig>
 <!--
# 设置 serif 衬线字体的读取顺序
-->
 <alias>
  <family>serif</family>
  <prefer>
        <family>Bitstream Vera Serif</family>
   <family>Microsoft YaHei</family>
  </prefer>
 </alias>
 <!--
# 设置 sans-serif 无衬线字体的读取顺序
-->
 <alias>
  <family>sans-serif</family>
  <prefer>
        <family>Bitstream Vera Sans</family>
   <family>Microsoft YaHei</family>
  </prefer>
 </alias>
 <!--
# 设置 monospace 等宽字体的读取顺序
-->
 <alias>
  <family>monospace</family>
  <prefer>
          <family>Bitstream Vera Sans Mono</family>
      <family>Microsoft YaHei</family>
  </prefer>
 </alias>
 <!--
# 全局字体的设置
-->
 <match target="font">
  <test compare="contains" name="family">
   <string>Tahoma</string>
   <string>verdana</string>
   <string>Arial</string>
   <string>Times New Roman</string>
  </test>
  <edit name="globaladvance">
   <bool>false</bool>
  </edit>
  <edit name="spacing">
   <int>0</int>
  </edit>
  <edit mode="assign" name="hinting">
   <bool>true</bool>
  </edit>
  <edit mode="assign" name="autohint">
   <bool>false</bool>
  </edit>
  <edit mode="assign" name="antialias">
   <bool>true</bool>
  </edit>
  <edit mode="assign" name="hintstyle">
   <const>hintfull</const>
  </edit>
 </match>
 <!--
# 单独设置微软雅黑字体的显示
-->
 <match target="font">
<test name="family" compare="contains">
<string>Microsoft YaHei</string>
<string>微软雅黑</string>
</test>
<edit name="rgba" mode="assign">
<const>rgb</const>
</edit>
<edit name="hinting" mode="assign">
<bool>true</bool>
</edit>
<edit name="autohint" mode="assign">
<bool>false</bool>
</edit>
<edit name="antialias" mode="assign">
<bool>true</bool>
</edit>
<edit name="hintstyle" mode="assign" >
<const>hintfull</const>
</edit>
</match>
<!--
# 单独设置 Bitstream Vera Sans 字体的显示
-->
<match target="font">
<test name="family" compare="contains">
<string>Bitstream Vera Sans</string>
</test>
<edit name="rgba" mode="assign">
<const>rgb</const>
</edit>
<edit name="hinting" mode="assign">
<bool>true</bool>
</edit>
<edit name="autohint" mode="assign">
<bool>false</bool>
</edit>
<edit name="antialias" mode="assign">
<bool>true</bool>
</edit>
<edit name="hintstyle" mode="assign" >
<const>hintslight</const>
</edit>
</match>
<!--
# 单独设置 Bitstream Vera Serif 字体的显示
-->
<match target="font">
<test name="family" compare="contains">
<string>Bitstream Vera Serif</string>
</test>
<edit name="rgba" mode="assign">
<const>rgb</const>
</edit>
<edit name="hinting" mode="assign">
<bool>true</bool>
</edit>
<edit name="autohint" mode="assign">
<bool>false</bool>
</edit>
<edit name="antialias" mode="assign">
<bool>true</bool>
</edit>
<edit name="hintstyle" mode="assign" >
<const>hintslight</const>
</edit>
</match>

<!--
# 单独设置 Bitstream Vera Sans Mono 字体的显示
-->
<match target="font">
<test name="family" compare="contains">
<string>Bitstream Vera Sans Mono</string>
</test>
<edit name="rgba" mode="assign">
<const>rgb</const>
</edit>
<edit name="hinting" mode="assign">
<bool>true</bool>
</edit>
<edit name="autohint" mode="assign">
<bool>false</bool>
</edit>
<edit name="antialias" mode="assign">
<bool>true</bool>
</edit>
<edit name="hintstyle" mode="assign" >
<const>hintslight</const>
</edit>
</match>
</fontconfig>