鱼C论坛

 找回密码
 立即注册
查看: 1508|回复: 8

[已解决]关于pow()函数的问题

[复制链接]
发表于 2018-12-21 14:22:55 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
为什么这个打印出来的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;
}

搞不明白,,,求解答
最佳答案
2018-12-21 15:21:57
本帖最后由 rencaixiaomeng 于 2018-12-21 15:24 编辑

[b]下面是 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 [__real@4008000000000000 (0316B38h)]  
003117D0 F2 0F 11 04 24       movsd       mmword ptr [esp],xmm0  
003117D5 F2 0F 2A 45 F8       cvtsi2sd    xmm0,dword ptr [a]  
003117DA 83 EC 08             sub         esp,8  
003117DD F2 0F 11 04 24       movsd       mmword ptr [esp],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 [b],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 [__real@4008000000000000 (0B86B38h)]  
00B817D0 F2 0F 11 04 24       movsd       mmword ptr [esp],xmm0  
00B817D5 83 EC 08             sub         esp,8  
00B817D8 F2 0F 10 05 48 6B B8 00 movsd       xmm0,mmword ptr [__real@4014000000000000 (0B86B48h)]  
00B817E0 F2 0F 11 04 24       movsd       mmword ptr [esp],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输出都正确
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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);

所以应该是浮点运算出现了误差
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-21 15:21:57 | 显示全部楼层    本楼为最佳答案   
本帖最后由 rencaixiaomeng 于 2018-12-21 15:24 编辑

[b]下面是 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 [__real@4008000000000000 (0316B38h)]  
003117D0 F2 0F 11 04 24       movsd       mmword ptr [esp],xmm0  
003117D5 F2 0F 2A 45 F8       cvtsi2sd    xmm0,dword ptr [a]  
003117DA 83 EC 08             sub         esp,8  
003117DD F2 0F 11 04 24       movsd       mmword ptr [esp],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 [b],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 [__real@4008000000000000 (0B86B38h)]  
00B817D0 F2 0F 11 04 24       movsd       mmword ptr [esp],xmm0  
00B817D5 83 EC 08             sub         esp,8  
00B817D8 F2 0F 10 05 48 6B B8 00 movsd       xmm0,mmword ptr [__real@4014000000000000 (0B86B48h)]  
00B817E0 F2 0F 11 04 24       movsd       mmword ptr [esp],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输出都正确
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-21 15:52:19 | 显示全部楼层
没错,编译器问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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 就行了吧??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-22 13:24:17 | 显示全部楼层
a b最好都改成double
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-12-22 14:31:28 | 显示全部楼层

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

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-22 16:41:31 | 显示全部楼层
你要是不需要小数就用整型,整型的平方函数自己就能写
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-12-24 08:12:38 | 显示全部楼层
rencaixiaomeng 发表于 2018-12-22 16:41
你要是不需要小数就用整型,整型的平方函数自己就能写

好吧..
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-3 02:14

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表