本文来自独孤伶俜的博客: pow函数以及math.h的一些坑 - 独孤伶俜

pow函数以及math.h的一些坑

起源

任何问题都有起源不是?这道问题其实是我刚学C语言的时候就自己遇到过。加上最近好多人问我类似于这种问题,于是决定写篇blog来解释一下。。。

问题描述

主要是C语言函数库中main.h中的pow(); 等函数有这个问题
问题的重现性和随机性还有得到的结果可能和你的编译器和cpu架构有关
下面是一个栗子:

#include<stdio.h>
#include<math.h>
int main()
{int i = 2;printf("%d\n",(int)pow(10,2));printf("%d\n",(int)pow(10,i));return 0;
}

将上面代码在 windows10,linux,Android下运行,得到结果如下:

咦 为啥windowds的结果会不一样呢

先看看pow()函数的原型定义

double pow  (double base, double exponent);

可以看到这个函数定义的 参数 和 返回值 都是 double 类型

这就意味着我们用int类型参与运算是需要强制转换~

接下来让我们来分析一下下~

  • 首先 我们得知道三大平台所对应的编译器是什么(win的cfree5.0用的的clang编译器,Android的C4roid 和 我的Deepin系统用的都是gcc编译器)
  • 其实 gcc和clang是两种完全不同的编译器,实现方式,编译步骤甚至都不一样,他们各有各的优势和劣势~,这里就不解释了~~(其实是解释不了!!!)~~
  • 最后 我们研究一下子这两编译器生成的中间代码

原来是编译器的锅!!!!!

我们看下中间代码~~(篇幅有限就不贴了)~~看到 :

Android和deepin的gcc编译器生成的代码把int变量的i值在调用pow函数前强制转换为double类型参与运算于是

int i = 2;
printf("%d\n",(int)pow(10,i));
//就变成了
printf("%d\n",(int)pow(10,(double)i));
//最终就成了
printf("%d\n",(int)pow(10,2.0));

而反观Windows下的Clang编译器 他没有把int的i变成double值,于是……

int i = 2;
printf("%d\n",(int)pow(10,i));
//编译器不知道i是个什么玩意,就会按double的形式把i的二进制数据取出来参与运算,,,
//所以i的值就不知道是啥了,,,运气好的话值可能不会差太远
//如果运气不好,,,那完蛋了,失之毫厘谬以千里也

而常数2为啥不会出错呢

printf("%d\n",(int)pow(10,2));
//这是因为两种编译器都会自动转换常数的类型
//就相当于
printf("%d\n",(int)pow(10.0,2.0));
//所以两个常数都是以double类型参与运算的
//而在遇到 %d 时 他会把之前准备好的(int)强制转换的值给printf 所以不会出错咯~

解决办法

说了这么半天,那到底咋解决呢!!!貌似有好几种方法 哈哈哈

方法一

//涉及整数的幂运算、阶乘等等你就不要使用pow(),自己写个函数随便起个名 不要用double就行了

方法二

//全程使用double运算 最后强制转换为int类型再输出什么的
//比如刚刚上面的代码可以写成这样
double i = 2.0;
int aut1 = (int)pow(10.0,i);
int aut2 = (int)pow(10.0,2.0);
printf("%d\n",aut1);
printf("%d\n",aut2;

方法三

//早日跳坑吧
//程序员没有女友
//有很大风险秃头
//钢铁直男
//But
//I love programming
//I love programming BUG
//I love you
//咳咳,我也爱读沈从文的《边城》

总结

其实不止pow函数,让我们看看math.h中的其他的函数原型

//三角函数
double sin(double);//正弦
double cos(double);//余弦
double tan(double);//正切
//反三角函数
double asin (double); //结果介于[-PI/2,PI/2]
double acos (double); //结果介于[0,PI]
double atan (double); //反正切(主值),结果介于[-PI/2,PI/2]
double atan2 (double,double); //反正切(整圆值),结果介于[-PI,PI]
//绝对值
int abs(int i); //求整型的绝对值
double fabs (double); //求实型的绝对值
double cabs(struct complex znum); //求复数的绝对值

上面这些函数大部分是用的double作为参数和返回值的,所以都有可能出现今天我们谈论的莫名其妙的bug,哈哈哈

尽量避免发生类型强制转换的情况发生,即使无法避免,也要写清楚(类型)强制转换,后面维护也会轻松不少~~~

pow函数以及math.h的一些坑相关推荐

  1. C语言标准数学函数库math.h之常用函数介绍

    C语言标准数学函数库math.h,一些数学计算的公式的具体实现是放在math.h里,具体有: 1 三角函数 double sin (double x);  x的正弦值 double cos (doub ...

  2. C语言数学函数库<math.h>及常用函数

    C语言数学函数库<math.h>及常用函数 一.<math.h> C语言中常用的一个数学函数库,里面涵盖了常用的数学运算,如求对数.指数.绝对值.三角函数.两数中最大数等.使用 ...

  3. 函数定义与调用,自己实现pow()函数对整数的运算

    // MyPow.cpp : 此文件包含 "main" 函数.程序执行将在此处开始并结束. //自己实现pow()函数#include <stdio.h>double ...

  4. 用<math.h>遇到 Redefinition of ‘y1‘ as different kind of symbol的问题

    大家好,我是程序员白菜. 前言 今天在用C语言写题目时发现了一个奇怪的问题. 费尽周折,解决问题之后.遂与大家分享,希望大家遇到之后可以快速解决. 问题如下 在vscode上面编译一下代码发现了问题. ...

  5. C语言math.h中的常用函数实例详解

    1.绝对值 2.取整和取余 3.三角函数 4.反三角函数 5.双曲三角函数 6.指数和对数 7.标准化浮点数 8.多项式 9.数学错误计算处理 1.绝对值 函数原型: int abs(int x); ...

  6. c语言中math的库函数,C语言中math.h库中的常用函数

    C语言中math.h库中的常用函数 int abs(int i) 返回整型参数i的绝对值 double cabs(struct complex znum) 返回复数znum的绝对值 double fa ...

  7. math.h数学函数

    函数定义 abs -- 绝对值acos -- 反余弦acosh -- 反双曲余弦asin -- 反正弦asinh -- 反双曲正弦atan2 -- 两个参数的反正切atan -- 反正切atanh - ...

  8. 常用math.h数学函数以及其他函数(吉林大学 孙立鑫)

    目录 1.math.h 头文件的常用函数 a.signbit(求浮点数是否含有符号) b.三角函数汇总 c.双曲函数 d.指数函数对数函数 e.分解浮点数(详解如下)frexp f.取浮点数的指数部分 ...

  9. 0020 C语言<math.h>函数库

    C语言的数学库函数之<math.h>函数库 1. 三角函数 double sin(double); 正弦 double cos(double); 余弦 double tan(double) ...

最新文章

  1. Sping面试题 Top 50
  2. 扩展KMP --- HDU 3613 Best Reward
  3. bolt在java,java neo4j bolt
  4. SLB vs CLB
  5. SpringBoot中怎样基于slf4j封装日志类输出日志
  6. C++中父类的虚函数必需要实现吗?
  7. Vue系列vue-router的动态路由使用(二)
  8. 背包——01背包Bone Collector(hdu2602)
  9. windows xp中安装PadWalker
  10. 卫星星历和历书的区别
  11. Oracle 各备份恢复环境下 SCN
  12. 拼多多微信页面h5 html,拼多多(7pdd)微信跳转h5页面打开app跳转任意url关注技术weixin://dl/business/?ticket...
  13. 如何成为靠谱的DotNet/C#程序员 (sunxiunan)(zz)
  14. activiti启动流程的过程中BUSSINESS_KEY没有获取到key
  15. java8通讯_8.进程通信
  16. Android 悬浮窗功能实现(微信语音通话悬浮窗效果实现)
  17. Streamsets相关资料汇总
  18. 2022电大国家开放大学网上形考任务-桥梁工程技术非免费(非答案)
  19. 关于Linux性能调优之内存负载调优
  20. Objective-C基础教程读书笔记(3)

热门文章

  1. 腾讯云服务器基础操作
  2. 产品经理原型篇——八大原则教你如何出赏心悦目的原型图
  3. Python3.6-Flask:制作一个语音对话问答机器人系统(网页版)
  4. Get UWP Version(不使用额外的nuget包或SDK)
  5. System.out. 输出到指定文件中
  6. 如何提高项目交付效率
  7. DBLE分库分表实战
  8. word转换为html为什么图片显示不了,word插入html 转换为docx图片不显示问题
  9. 2015年国网计算机考试试题,2015全国计算机等级一级MS Office考试试题(回忆版)
  10. Kubuntu安装N卡驱动教程