GNU C标准库提供了很多工具用来简化编程,包括各种数学工具,对于时间的处理接口以及对系统资源的访问等等。本部分为GNU C标准库阅读记录第二部分,主要包括像随机数、浮点运算操作及定时时钟设置以及进程自己睡眠等操作。
Mathematics
标准库在math.h
头文件中声明了包括三角函数在内的很多数学函数用来计算,而在 complex.h
中提供了对复数的支持以及各种用于复数的计算。针对浮点类型的函数提供了三种变体,分别是对 double
、float
和long double
的支持,其中 float
的计算是最快的,另外两个分别精度比较高。
以三角函数为例,分别存在sin
、sinf
和sinl
这三个函数,针对 double
、float
和 long double
进行计算。对于复数的支持函数一般叫做如 ccos
和 ctan
等,后缀如ccosf
同样表示对float
的支持。反三角函数如反正弦函数位 asin
,三角函数中还有如双曲正弦函数 sanh
等。
指数函数一般用 exp
表示对double
的处理,expf
表示对float
的处理,另外还提供如exp10
和 exp2
等函数表示10或者2的指数。相应的对数函数同样有 log
、logf
、及log10
等。比较通用的指数函数是pow
和 powf
,可以指定基数和阶。另外 sqrt
可以用来开平方。
伪随机数
随机函数产生的一般不是真正的随机数,而是伪随机数并且因为循环周期足够大可以忽略,随机数产生器通过记住一个种子值并且用它来计算下一个随机数并同时计算一个新的种子。尽管程序中产生的数看起来是不可预测的,但是程序每次的执行随机数序列都是相同的,这是因为开始的种子总是相同的,当调试程序的时候是方便的,但是如果希望每次都有不同的随机数却是无用的。针对这一点,可以让种子基于当前时间来产生随机数。
标准C中的随机函数是 rand
,存在于stdlib.h
中产生的随机数范围是 0 到 RAND_MAX,最大数在GNU C中32位机器上是最大的有符号整型数,使用 srand
可以设置种子,默认情况下使用 rand
的种子是1。在BSD系统中随机函数位random
和 srandom
。
Arithmetic Functions
标准C同样提供了基本的运算操作比如 div
,可以用来计算商和余数。对于浮点类型包括很多运算,比如 fpclassify
可以判断给定的浮点类型是否是有限还是0,还是无限数,另外对应还存在 isfinite
和 isnan
等判断函数。浮点运算的时候可能会出现错误,比如无穷大数的加减,除0操作,上溢出和下溢出等可能会导致出现 SIGFPE 信号。
对于运算存在如绝对值 abs
及正则化函数 frexp
等操作,对于浮点数的舍入,存在多种舍入方式,比如向上舍入到整型 ceil
函数,向下舍入到整型 floor
函数,还有截断小数函数 trunc
, 而 rint
函数和 round
函数使用当前的舍入模式来处理。
Date and Time
GNU函数库提供了对日期和时间的支持,主要位于头文件 time.h
中,对于经过的时间可以使用 difftime
来计算,参数为日期时间,单位是秒。对于时间的处理用得最多的结构是 struct timeval
, 它包含两个成员,一个代表经过的时间 tv_sec
,另一个是 tv_usec
,表示生于的经过时间,用微秒表示,还可以使用 struct timespec
,只不过它能够表示更精细的时间。使用 gettimeofday
可以获取当前的时间,获取结构为 struct timeval
, 还可以使用 settimeofday
设置当前的时间。
对于CPU的时间可以用 clock
函数查询,而对于处理器时间的查询需要借助 struct tms
,使用 times
函数来获取。
对于日期时间,使用 time
可以直接获取当前时间,而 stime
则可以设置系统时钟。但是 time
函数只是返回 time_t
类型,也就是以秒为单位,如果需要获取更精确的时间需要借助 struct timeval
结构和 gettimeofday
函数。使用 adjtime
可以对系统时钟进行微调。
设置定时器
函数 alarm
和 setitimer
提供了让进程中断自己的机制,可以通过设置一个时钟,当时间用完的时候,进程就会收到一个信号。每个进程都可以由三种独立的内部时钟:
- 真正的时钟用来计算经过的时间,在时钟到期时发发送 SIGALRM 信号
- 虚拟时钟计算进程的处理器时间,时钟到期发送 SIGVTALRM 信号
- 一个测量时钟既计算进程使用的处理器时间,也计算进程系统调用的时间,当时钟到期时发送 SIGPROF 信号
在设置时钟时,每种类型只能设置一个,多次设置会重置时钟。在调用 alarm
和 setitimer
之前就应该设置好相应信号的处理函数。
睡眠
使用 sleep
能够方便的让程序睡眠一定的时间,当然如果有信号出现的话会提前醒来。另外 nanosleep
可以睡眠更精确的时间。