- 无符号数: x >> k 产生除以2的k次幂向下取整
- 有符号数: (x + (1<<k) - 1) >> k 产生除以2的k次幂向下取整
- 浮点加法可交换, 不可结合
- 除无穷和NaN外, 大多数值具有加法逆元(+无穷-无穷=NaN, NaN + x = NaN)
- 浮点加法满足单调性: 如果a >= b, 对于任意a,b,x, 除了NaN有x + a >= x + b
- 浮点乘法封闭(可能产生无穷大和NaN), 可交换, 幺元为1.0
- 由于可能溢出,舍入而失去精度, 不具可结合性.
- 浮点乘法在加法上不具备分配性
- 对于任意a,b,c(都不为NaN)有: a >= b 且 c >= 0 --> a * c >= b * c; a >= b 且 c <= 0 --> a * c <= b * c;
- a != NaN, a * a >= 0;
- int转float: 不会溢出, 可能被舍入
- int或float转double: 保存精确的数值
- double转float: 可能溢出成+无穷或-无穷, 还可能被舍入
- float转double或int: 值向零舍入
/*detect whether arguments can be added without overflow*/
/*WARNING: This code is buggy*/
int tadd_ok(int x, int y) {
int sum = x + y;
return (sum-x == y) && (sum-y == x);
}
解答: 因为模数加法构成阿贝尔群具有交换性和逆元 故无论是否溢出以下等式成立: (x + y) -x = (x - x) + y = (0) + y = y (x + y) -y = x + (y - y) = x + (0) = x 所以返回值始终为1
int tmult_ok(int x, int y) {
int p = x * y
return !x || p / x == y;
}
证明:见p104
// bug!
uint64_t asize = ele_cnt * (uint64_t) ele_size;
void *result = malloc(asize);
上面这段代码没有任何改进, 因为malloc的参数时size_t,任然会被截断,造成溢出;
// fix bug
uint64_t required_size = ele_cnt * (uint64_t)ele_size;
size_t request_size = (size_t)required_size;
if (request_size != required_size) {
// overflow
return;
}
void *result = malloc(request_size);
if (result == NULL) {
// malloc failed
return NULL;
}
// do something