程序开发之数学基础(一)

这个系列不是一个系统性地学习数学相关知识的专题,更多是一种程序开发中基础性数学知识的归纳和总结。

让我们从数字开始说起吧。

1. 按位计数法
人类解决问题一个方法就是从大量问题中分析和定义出系统的、普遍的、简单的规则,以此快速解决同类问题。

定义指数法则如下:
N^a * N^b = N^(a+b)

这个指数法则有什么含义呢?有:
N^0 = 1

因为:N^0 * N^1 = N^(0+1) = N^1
因此:N^0 = (N^1) / (N^1) = 1

还有:
N^(-b) = 1 / (N^b)

因为:N^(-b) * N^b = N^(b-b) = N^0 = 1
因此:N^(-b) = 1 / (N^b)

由此,在以N为基数的情况下,一个整数可以被表达为:
Ak * N^k + ... + A2 * N^2 + A1 * N^1 + A0 * N^0

而一个小数可以被表达为:
Ak * N^k + ... + A2 * N^2 + A1 * N^1 + A0 * N^0 + B0 * N^(-1) + B1 * N^(-2) + ...

这里值得强调的是,通过定义这样一个简单的指数规则,人类获得了强大的工具。这不是记忆力的问题,而是想象力的问题。请记住这种思维方式。

2. "0" 的故事

0是人类智慧的又一体现。公元前3000年,巴比伦人就已经懂得使用零来避免混淆。

在公元5世纪时,“0”已经传入罗马。但罗马教皇凶残而且守旧。他不允许任何人使用“0”。有一位罗马学者在笔记中记载了关于使用“0”的一些好处和说明,就被教皇召去,施行了酷刑,使他再也不能握笔写字。这里我想说的是,并非所有的人都有足够的智力能意识到先进的东西。

国际上规定0是最小的自然数。我国自1993年起也规定0属于自然数。

用0来表示没有或者用来占空位,可以极大地简化规则。

3. 计算机中除0的结果

以单精度浮点小数为例。一个合理的数值除以0,会产生INF值,也就是无穷大。

inf 0x7f800000 (符号位:1,指数位:+127,尾数位:0)
-inf 0xff800000 (符号位:0,指数位:+127,尾数位:0)

使用0除以0,或者执行非法操作,如Sqrt(-1),则会产生NAN值,也就是无法被计算机表达的非法数字:
-nan(ind) 0xffc00000 (符号位:1,指数位:+127,尾数位:0x400000)
nan 0x7fc00000 (符号位:0,指数位:+127,尾数位:0x400000)

对于单精度浮点数来说,只要指数位为+127,尾数为零就是inf;而指数位为+127,尾数位为非零时就是Nan。这意味着Nan并非只有一个,而是一族。不过,大多数程序仅在检测一个数字是否为Nan时,仅考虑尾数的第一个bit,而忽略其后的bits。

注:IEEE 754所定义的单精度浮点数格式为:s eee eeee e xxx xxxx xxxx xxxx xxxx xxxx


4. 60进制

约公元前3200至2340年的古巴比伦人,使用了60进制计数法。在这种计数法下,一个数字可以表示为:
Ak * 60^k + ... + A2 * 60^2 + A1 * 60 + A0

这种计数法至今仍然在时间、角度计算中被使用。原因如下:
- 将圆周定义为360度,则采用60进制,可以轻易地6等分、5等分、4等分、3等分、2等分一个圆周或者60度角而不产生小数位
- 一个等边三角形的任意一个内角刚好是60度
- 一个圆的内接正六边形刚好等分圆周

例子:
- 北极圈的纬度 66°33'38" N
- 北回归线的纬度 23°26'22" N
- 耶路撒冷的经度 35°13' E

如果要得到具体的度数,则 66°33'38" = (66 * 60^0 + 33 * 60^(-1) + 38 * 60^(-2))°

5. 10进制
不做阐述

6. 2进制
以2为基数的表达方法。

2进制采用0和1来表达,这就给了我们各种奇淫巧技的施展空间。

判断一个整数X能否被2整除(是否为偶数):
bool canDivBy2 = ((X & 1) == 0);
也可以写成:
bool canDivBy2 = ((X % 2) == 0);

计算一个数字除以2的n次方的结果:
int divBy2n = (X >> n);
乘以2的n次方:
int mulBy2n = (X << n);

不使用临时变量,交换两个数字:
a ^= b;
b ^= a;
a ^= b;

判断一个整数X是否为2的幂:
bool isPowOf2 = ((X != 0) && ((X & (~X + 1)) == X));

根据整数X,获取小于或等于X的最大的2的幂:

unsigned int getPowerOf2Floor(unsigned int x)
{
    x = x | (x >> 1);
    x = x | (x >> 2);
    x = x | (x >> 4);
    x = x | (x >> 8);
    x = x | (x >> 16);

    return x - (x >> 1);
}

根据整数X,获取大于或等于X的最小的2的幂:
unsigned int getPowerOf2Ceil(unsigned int x)
{
    x = x - 1;
    x = x | (x >> 1);
    x = x | (x >> 2);
    x = x | (x >> 4);
    x = x | (x >> 8);
    x = x | (x >> 16);

    return x + 1;
}

7. 64进制 (Base64)
编码后数据长度大约为原长的135.1%。

8. 斐波那契编码 (Fibonacci coding)
使用斐波那契序列作为基数的编码方式。这种编码方式在某个位被破坏或者发生偏移后,仅破坏位置附近的编码会发生错乱,而后续的编码依然能够正常读取。这是其他编码方式所不具备的。

不做深入阐述。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值