在C、C++中,数学函数的参数和返回值一般都要求是浮点型的,那么如果输入一个整数或者整数表达式作参数会怎么样呢?
以计算平方根的函数为例,共有3个函数,分别是sqrt, sqrtf, sqrtl,函数原型如下:
float sqrtf( float arg );
double sqrt( double arg );
long double sqrtl( long double arg );
按要求参数不能是整数,返回值也不能是整数。所以按理sqrt(9)是不符合函数要求的,而应写成sqrt(9.0),但实际上,用sqrt(9)也能输出正确结果。这是因为,在调用函数时,如果传入一个非接受类型的参数,会被隐式转换为接受的类型。sqrt(arg)函数被定义为接受double类型的参数,由于这个参数的类型已知,当传递int类型时,编译器会自动隐式转换为 double类型。
这里面有一个很有意思的事情,就是sqrt(arg)函数将参数arg由int转为double类型时,它实际上是将arg作为一个整体来转换的。比如sqrt(19/2)的计算过程:
1)把19/2视为一个整体,先计算出它的值。因为分子分母都是整数,所以输出结果也是整型,计算结果会舍去小数部分,即19/2=9。
2)将19/2的结果由int型转换为double,即将9转换为9.0,然后再计算sqrt(9.0)的值。
所以sqrt(arg)相当于sqrt((double)(arg))。
这一点其实也很好理解,函数的原型就是sqrt(arg),它的参数归根到底只有arg,至于arg是怎么计算来的,取决于它本身的表达式,和函数本身没有关系(即19/2的值只与19/2这个表达式本身有关,和sqrt函数无关)。sqrt(arg)只管把arg转化为浮点型,然后计算它的算术平方根。
注意sqrt((double)(arg))参数中的这两个括号都是非常有必要的,感兴趣的可以用下面的代码测试一下,就可以看出其中的玄机。
#include<stdio.h>
#include<math.h>
int main(){
printf("%f\n", sqrt(9.0));
printf("%f\n", sqrt(9));
printf("%f\n", sqrt(19/2));
printf("%f\n", sqrt((double)(19/2)));
printf("%f\n", sqrt((double)19/2));
printf("%f\n", sqrt(19/(double)2));
printf("%f\n", sqrt(19.0/2));
return 0;
}
此外sqrt的返回值也是double类型的,所以用printf输出时也不能用%d(如用了会输出0),而要用%f。注意,违反以上要求编译时也不会报错,但输出结果会有问题。