1809228982 发表于 2018-12-21 14:22:55

关于pow()函数的问题

为什么这个打印出来的b是124呢、
#include <stdio.h>
#include <math.h>
int main()
{
    int a = 5;
    int b = pow(a,3);
    printf("%d",b);
   
    return 0;
}


而 这样就是正确的125了#include <stdio.h>
#include <math.h>
int main()
{
   // int a = 5;
    int b = pow(5,3);
    printf("%d",b);
   
    return 0;
}


搞不明白,,,求解答

calton007 发表于 2018-12-21 14:50:02

1、C/C++中的数学函数
原型:在TC2.0中原型为extern float pow(float x, float y); ,而在VC6.0中原型为double pow( double x, double y );
头文件:math.h/cmath(C++中)
功能:计算x的y次幂。
返回值:x不能为负数且y为小数,或者x为0且y小于等于0,返回幂指数的结果。
返回类型:double型,int,float会给与警告!

2、pow函数的重载
C++提供以下几种pow函数的重载形式:
double pow(double X,int Y);
float pow(float X,float Y);
float pow(float X,int Y);
long double pow(long double X,long double Y);
long double pow(long double X,int Y);

所以应该是浮点运算出现了误差

rencaixiaomeng 发表于 2018-12-21 15:21:57

本帖最后由 rencaixiaomeng 于 2018-12-21 15:24 编辑

下面是 int b = pow(a,3);的反汇编代码
003117C5 83 EC 08             sub         esp,8
003117C8 F2 0F 10 05 38 6B 31 00 movsd       xmm0,mmword ptr
003117D0 F2 0F 11 04 24       movsd       mmword ptr ,xmm0
003117D5 F2 0F 2A 45 F8       cvtsi2sd    xmm0,dword ptr
003117DA 83 EC 08             sub         esp,8
003117DD F2 0F 11 04 24       movsd       mmword ptr ,xmm0
003117E2 E8 40 F9 FF FF       call      _pow (0311127h)
003117E7 83 C4 10             add         esp,10h
003117EA E8 F2 F8 FF FF       call      __ftol2_sse (03110E1h)
003117EF 89 45 EC             mov         dword ptr ,eax



下面是 int b = pow(5,3);的反汇编代码
00B817C5 83 EC 08             sub         esp,8
00B817C8 F2 0F 10 05 38 6B B8 00 movsd       xmm0,mmword ptr
00B817D0 F2 0F 11 04 24       movsd       mmword ptr ,xmm0
00B817D5 83 EC 08             sub         esp,8
00B817D8 F2 0F 10 05 48 6B B8 00 movsd       xmm0,mmword ptr
00B817E0 F2 0F 11 04 24       movsd       mmword ptr ,xmm0
00B817E5 E8 3D F9 FF FF       call      _pow (0B81127h)
00B817EA 83 C4 10             add         esp,10h
00B817ED E8 EF F8 FF FF       call      __ftol2_sse (0B810E1h)
00B817F2 89 45 EC             mov         dword ptr ,eax

看不懂没关系,这些指令有一条是关键, int b = pow(a,3);的反汇编代码 第4条是 cvtsi2sd,这个指令的作用就是把整数转换成双精度浮点数,而在下面int b = pow(5,3);的反汇编代码则没有这条指令
因为int b = pow(5,3),5和3都是常量,在编译的时候,编译器知道pow接受的是double,就把5和3直接转成double型,这样在运行时就不用再转换类型
而 int b = pow(a,3) 因为a是变量,编译器不知道变量里面具体数值,就让程序运行时自己计算类型转换的值而可能出现这个误差


不过现在的编译器应该很少会出现这种情况,我用VS2015输出都正确

ba21 发表于 2018-12-21 15:52:19

没错,编译器问题。

1809228982 发表于 2018-12-22 10:42:26

rencaixiaomeng 发表于 2018-12-21 15:21
下面是 int b = pow(a,3);的反汇编代码
003117C5 83 EC 08             sub         esp,8
003117C8 F ...

看不懂.... 感觉就是说把 a 转为double 就行了吧??

rencaixiaomeng 发表于 2018-12-22 13:24:17

a b最好都改成double

1809228982 发表于 2018-12-22 14:31:28

rencaixiaomeng 发表于 2018-12-22 13:24
a b最好都改成double

这么改感觉占的空间更大了,,是不是应该这么写,,这样应该比较好吧??
#include <stdio.h>
#include <math.h>
int main()
{
    int a = 5;
    int b = a*a*a;
    printf("%d",b);
   
    return 0;
}


rencaixiaomeng 发表于 2018-12-22 16:41:31

你要是不需要小数就用整型,整型的平方函数自己就能写

1809228982 发表于 2018-12-24 08:12:38

rencaixiaomeng 发表于 2018-12-22 16:41
你要是不需要小数就用整型,整型的平方函数自己就能写

好吧..
页: [1]
查看完整版本: 关于pow()函数的问题