首页
社区
课程
招聘
[原创][随笔]从char类型到玛雅历法
2013-1-5 20:06 7516

[原创][随笔]从char类型到玛雅历法

2013-1-5 20:06
7516
【随笔】从char类型到玛雅历法

今天看书,看到一段代码,下面是其中的一个申明部分,是记录每月天数的表。

static char daytab[2][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

复制代码
一开始并没在意数组的类型以及数组中的元素类型,后来看到书上特意提了一下。
“这里之所以将daytab的元素声明为char类型,是为了说明在char类型的变量中存放较小的非字符整数也是合法的。”


恩,就是有点小疑问= =。。关于这个存放较小的非字符整数的合法性问题。= =。。各位怎么看。。= =


首先,这个问题跟声明无关。

在C语言中,char类型,是整数类型的一种。

假定在你的系统的某个C实现上面,一个char类型数据占用了1个字节的长度,即8 bits。

我们知道,在一个bit中的,要么是一个0,要么是一个1。

所以,8个bits组成的序列,可以表示2的8次方个不同位向量,即

0000 0000
0000 0001
0000 0010
……
1111 1110
1111 1111

一共256个。

那么,它们可以和256个整数一一对应。

即所有的char类型的数据所构成的集合中的元素,总可以和256个整数一一对应。

这256个整数,可以是[0,255],也可以是[-128,127],也可以是其他的整数集合。

在我的系统上,文件 /usr/include/limits.h 给出了本系统上某个C实现(GCC)的约定:
/* Number of bits in a `char'.  */
#  define CHAR_BIT      8

/* Minimum and maximum values a `signed char' can hold.  */
#  define SCHAR_MIN     (-128)
#  define SCHAR_MAX     127

/* Maximum value an `unsigned char' can hold.  (Minimum is 0.)  */
#  define UCHAR_MAX     255

/* Minimum and maximum values a `char' can hold.  */
#  ifdef __CHAR_UNSIGNED__
#   define CHAR_MIN     0
#   define CHAR_MAX     UCHAR_MAX
#  else
#   define CHAR_MIN     SCHAR_MIN
#   define CHAR_MAX     SCHAR_MAX
#  endif
注意上面最后一小节。其中的“__CHAR_UNSIGNED__”宏是否被定义,是由GCC根据我的机器(严格地说,是目标机器)的背景情况决定的(用户不可干预),当且仅当我的机器满足“char类型是一种符号的整数类型”这个背景条件时,这个宏将被定义。

在我这里,现场的实际情况是:这个宏没有被定义,即:作为GCC的目标机器,具有“char类型是一种符号的整数类型”的属性。

此时,我们回到上面那一个小节:因为“__CHAR_UNSIGNED__”宏没有被定义,则GCC将

“CHAR_MIN”宏定义为“SCHAR_MIN”宏,即整数-128。
“CHAR_MAX”宏定义为“SCHAR_MAX”宏,即整数127。

所以,在这个实现场合中,所有char类型的数据之集合中的元素,可以与[-128,127]这个整数集合中的元素一一对应。

或者,干脆直接说:char类型的数据之集合中的元素,是从-128到127这256个整数。

而当我们利用“字符常量”这种机制(特别注意:字符常量不是所谓的“char类型常量”,后者在C语言中是不存在的!)来为char类型的数据对象赋值的时候,一种“字符-整数”的对应关系,就是一个基本前提。


这种对应关系的法则,由不得你来决定,一般情况下,它会遵照绝大多数计算机基础教材的附录(通常是附录1或附录A,可见其基要性)中的《ASCII字符集》所揭示的字符与整数的对应关系。

比如:
字符'\0'对应且仅对应着整数0(十进制);
字符'\1'对应且仅对应着整数1(十进制);
字符'\2'对应且仅对应着整数2(十进制);
……
字符'\10'对应且仅对应着整数8(十进制) —— 可见,斜杠后面跟着的是一个八进制整数;
字符'\11'对应且仅对应着整数9(十进制);
……
字符'\r'对应且仅对应着整数13(十进制) —— 转义序列“\r”指代一个CR(Carriage Return)字符,即回车。回车字符的ASCII编码是13(十进制);
……
字符'\x10'对应且仅对应着整数16(十进制);—— 可见,斜杠与x后面跟着的是一个八进制整数;
……
字符'A'对应且仅对应着整数65(十进制)—— 字符A的ASCII编码是65(十进制);
字符'B'对应且仅对应着整数66(十进制);
……
字符'a'对应且仅对应着整数97(十进制);
字符'b'对应且仅对应着整数98(十进制);
……

这样的对应关系,实际上,就是将char类型的数据之集合中的[0,127]这个真子集中的元素,与[0,127]这个整数集合中的元素一一对应。

同样要特别注意的是:作为表达式的
'A'
—— 其类型是int,而非char!


即“'A'”这样的字符常量,其数据占用的宽度与一个int类型数据所占用的宽度是一致的,通常是32bits,而不是8bits。
char x;
x = 'A';
这样的赋值运算,蕴含了将一个通常为32bits的数据“截短”为8bits的数据的转换过程(这种情况是合法的)。

回到楼主的题目。。。

人类社会目前所最普遍使用的历法 —— 格列高利历(俗称公历),将一年分为12个月,并按照大体均等的原则规定了每个月的日子数,这个日子数不会超过31。

因为[0,31](本题额外多设了一个0)这个整数集合,是[-128,127]或[0,255]的一个真子集;或者,换一种看法:[0,31]这个集合中的任何元素,相对于它的超集中的最大整数即127或255来说,都是“较小的”,所以,[0,31]这个整数集合中的任何元素,都可以与char类型数据集合中的元素单射地对应。

简言之,0、28、29、30、31这五整数,完全可以用char类型来存储、读取和表达。

注意:在代码(数组元素的初始化部分)中出现的这些样式的整数(除了0之外),将被视为关于十进制常量的表达式,它们的类型是int,当然关于常量“0”的那个表达式,其类型也是int,所以,它们均占用了通常是32bits的长度。(这个“整数常量的代码被编译器解释/认可为int类型”的基本原则,请参见键盘农夫(KBTiller)大虾的《狂人C》

同前述之理,用这样的表达式为char[][]类型的数组之元素初始化,就会蕴含一个将数据“截短”为8bits的数据的转换过程(这种情况是合法的)。


综上所述,由这五整数构成的一个二维数组(2x13个元素),可以是static char [2][13]类型的。

考虑到提设的巧妙 —— [0,31]这个整数集合(含32个整数),以ASCII编码看来,恰巧是“控制字符(Control Character)”区间。

控制字符,也叫“非打印字符(Non-Printing Character)”,它们不仅是“不可见的”,而且是可以用来操控终端设备的(最早是操控TTY即电传打字机的)。

经常接触终端的用户,大多都有这种经验:在由“可见字符”组成的序列中,搀杂控制字符,很可能导致打印(显示)的混乱。

所以,一些用户对控制字符,是敬而远之的。

或许,他们有“将控制字符保存进char类型的对象中会导致数组元素序列混乱”的顾虑。

而作者在这里所说的“在char类型的变量中存放较小的非字符整数也是合法的”,应该就是为了破除这种顾虑。


这里的“非字符”,应该就是指控制字符(作者在这个语境中,将不可见字符当作“非字符”看待)。

而这里的“较小的”一词,应该是对于“非字符整数”本身的描述(即“非字符整数”在整个ASCII字符集当中,是“较小的”),而不是一个限制性定语(指整个“非字符整数”集合中“较小”的那个部分)。

讲到这里 —— 一个颇为微妙的事情,似乎呼之欲出 ……

我们注意到:在ASCII字符集中,控制字符(除了DEL字符)全部位于前32个(即从0到31)。

32这个数字,是2的一个正整数次幂,即2的5次方。

而大多数历法中的一个月的日子,都在30附近 —— 这是因为月相的变化周期(即朔望月)是大约30天左右,所以叫“月(Month/Moon)”。

也就是说:

朔望月的长度,是“一天”长度的约30倍。

“一天”传统上都是基于“视太阳”的“太阳日”,即地球相对于“视太阳”自转一周的时间(不同于地球“自己”相对于遥远恒星的自转一周的时间),也就是观测地的一个正午到下一个正午(可以藉由日晷测量)的时间。

而我们今天普遍使用的格列高利历(俗称公历),遵守“以太阳回归年为一年”的原则。(太阳回归年:在地球看来,太阳从黄道上的一点再回到该点的周期。)

可以藉由观测得知,一个太阳回归年大约是365.24个“太阳日”,这就使得:我们公历的一年有365日或置闰的366日。

公历将它的“年”与传统的朔望月相调和,就使得:公历需要有12个月,且每个月的日子数在30或31附近。

30或31这个数,和2的5次方即32,非常接近,我并不想武断地下一个“这不是巧合”的结论,但是,这是否能揭示一些群族将二进制/八进制/十六进制/三十二进制作为历法基础的可能性?

不过,这还得和中国传统巫术文化如《易》中所体现的所谓“二进制思想”、“八进制思想”或“六十四进制思想”区别开来。

我的意思是:朔望月相对于太阳日的倍数(大约是30)—— 即太阳-地球-月球三天体的运动关系,是否可以用“2正整数次幂之进制”的计数法来*解释*?

我觉得,这种希望非常渺茫。上述天体的运动关系,倒是揭启了人类对于“12进制”、“60进制”和“360进制”的自觉运用,但却不是二进制/八进制/十六进制/三十二进制。

那我们调转方向,查考一些“非主流”民族的计数制/进位制。

比如,把全人类“折腾”了一番的玛雅民族(和他们的历法)。

玛雅民族(玛雅文明)的计数制/进位制和他们的历法(即对天体运行规律的揭示)是分不开的。

玛雅文明普遍采用18进制和20进制(已经可以注意到:18与20的乘积是360)。

20进制,基于玛雅文明的每个月份的日子数,即他们的一个月有20天。

为什么他们的一个有20天,而不是30天?

因为玛雅人采用双手双脚的指/趾端数总和,即20,来作为他们计数的基本基数。

而他们倚靠对金星的观测,来确定太阳年。这个单位太阳年的长度是365天多一点。

在晚上欧巴桑没有电视可看、屌丝没有网可上、美白富没有夜店可泡、仰望星空时也没有大气污染和光污染干扰的古代玛雅人看来,金星是夜晚天空中亮度仅次于月亮的天体。(有人藉此来佐证“古代玛雅时期,月球尚不存在”,这真是匪夷所思、令人难以置信!)

玛雅文明利用太阳-地球-金星三天体的运动关系,确定了他们的历法。在一个月有20天的情况下,为了调和约365天多一点的太阳年,就要把一年分为18个月或置闰的19个月(第19个月很短,只有5天多一点)—— 这个叫Haab历。

这样,我们就不难理解,玛雅文明采用了18进制和20进制的计数法。

又及,其实,玛雅人还有一种更为首要的历法:即260天(260 = 13 x 20)的年历。但其中的因子13,目前没有证据表明跟天体运行有关。一些零散的学说,认为260天跟人的妊娠周期(以最后一次期经不至到分娩计日)有关 —— 这个叫Tzolkin历。

那么 …… 采用基于二进制/八进制/十六进制/三十二进制的历法的“民族”,恐怕仅仅存在于计算机世界里了,呵呵 ……  

以上,仅供参考,呵呵 —— :)

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞3
打赏
分享
最新回复 (10)
雪    币: 297
活跃值: (120)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
淡定疯着 2013-1-5 21:06
2
0
哈,一看标题就猜到是您老写的啦
雪    币: 30
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
huma 2013-1-5 23:26
3
0
我看完了~~~~~~~~~~~~~~~
雪    币: 63
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
bluegb 2013-1-6 00:01
4
0
每帖必看...支持楼主...话说楼主的知识面真是一个广...厉害.....
雪    币: 119
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
叶梦 2013-1-8 18:19
5
0
历法使用X进制,计算机使用2进制的,他们之间的联系不在于2与X有没有关系。他们的联系在于人类一个最基本的思路,“简单,朴素的思考问题”。因为一年是365,所以恰好有了18*20,12*30也说的过去,所以也有了,这样刚好约等于365.而计算机2进制的原因在于电路的最简单就是二态,开或关,对应高电压与低电压,对应逻辑真与假。

我觉得但凡复杂的东西,着眼最细小处看,都是人类最朴素的想法。
雪    币: 6
活跃值: (980)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lookzo 2013-1-10 11:00
6
0
lz的文章我只能膜拜,无法看懂
雪    币: 508
活跃值: (89)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
Hefe 3 2013-1-10 16:19
7
0
浏览过楼主系列文章,跪了!
雪    币: 3
活跃值: (81)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
moonspot 2013-1-10 21:21
8
0
惭愧,没看明白。过些天再来看。
雪    币: 660
活跃值: (1703)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
pushmop 2013-1-10 23:02
9
0
喜欢楼主的文章。
雪    币: 23
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小P孩儿 2013-1-10 23:36
10
0
学的深了拓展也深
雪    币: 306
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
baohongyu 2013-1-12 10:27
11
0
我喜欢楼主的态度
游客
登录 | 注册 方可回帖
返回