下面的代码没有给予正确的输出。
#include <stdio.h>
#define PI 22/7
#define AREA(r) PI * r * r
int main() {
printf("Pi: %d\n", PI);
printf("Area: %d\n", AREA(8));
return 0;
}
而下面的代码给出了正确的(最接近的)输出。
#include <stdio.h>
#define PI 22/7
#define AREA(r) r * r * PI
int main() {
printf("Pi: %d\n", PI);
printf("Area: %d\n", AREA(8));
return 0;
}
这些代码究竟有何不同?
为甚么会这样呢?我实在不明白上述两个密码会给予甚么分别。
3条答案
按热度按时间olmpazwi1#
问题出在
PI
宏上:这样做有两个问题:(1)它没有被括号括起来,以防止它的一部分与表达式的其他部分绑定得更紧,(2)它是在做整数除法。
如果
22/7
本身就是3
,这可能不是您想要的,但是AREA
宏也有问题,它看起来像这样:扩展
PI
后,这相当于:假设
r
是一个简单的变量或常量,则等价于:如果
r
是一个整数,它仍然在做整数除法,但它只在末尾截断,所以结果会更精确。请注意,
AREA
自身存在两个问题:(1)它没有将参数r
括在括号中,(2)它没有将表达式作为一个整体括在括号中。对于问题(1),假设将
2+3
作为r
传递,由于乘法比加法关联更紧密,这显然不会达到您的目的。如果你想得到精确的结果,你通常会用精确的浮点值来表示pi,而不是用极不精确的近似值22/7。但是如果你确实想用22/7,你还是应该用浮点值来表示:
然后可以修复
AREA
:这将适当地保护参数和最终结果,防止它们在展开后重新关联,但注意结果将具有类型
double
,还要注意其参数r
被求值两次。但是更好的pi近似值是可取的,在Linux上,
math.h
导出M_PI
,这要精确得多。x8goxv8g2#
试着展开宏,第一个宏是22 / 7 * 8 * 8,所有的值都是整数,所以会有舍入误差,计算结果基本上是3 * 8 * 8 = 192。
第二个表达式为8 * 8 * 22 / 7。因此计算结果为1408 / 7 = 201。
l7wslrjt3#
乘法和除法是从左到右进行的。因此,第一个示例中的AREA(8)扩展为22/7 * 8 * 8,其计算如下:((((22/7)* 8)* 8),即3 * 8 * 8 = 192。
另一个变量给出:((((八 * 八)* 二十二)/七)=(六十四 * 二十二)/七=一千四百零八/七=二百零一。
如果你想要更好的精度,使用浮点数,例如#define PI(22.0/7.0)或者,为什么不使用一个更好的近似值:#定义PI(3.141593)
但是你应该在printf中使用%f。(如Jabberwocky所评论的)