马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本文泉源:C语言根本概念——讨论sqrt()和pow()函数与整数的关系.
<hr> 根据C尺度,float范例必须至少可以大概表现6位有用数字,且取值范围至少是10-37〜10+37。此中,6位有用数字的要求意味着float范例必须可以大概正确表现如33.333333如许的数值;而取值范围的规定则使其可以大概方便地表现诸如太阳质量(2.0e30千克)、质子电荷量(1.6e-19库仑)等极大或极小的数值。
在大多数C语言实现中,单精度浮点数采取IEEE 754尺度的32位表现法,此中尾数部分占23位(223= 8,388,608),相当于7位十进制数。这意味着float范例在转换为十进制后,最多可以包管7位有用数字的精度,完全满意C尺度对6位有用数字的要求。须要注意的是,第7位之后的数字大概不正确。雷同地,double范例的尾数占52位(252),可表现约16位十进制有用数字,或63位(263)时可表现约19位十进制有用数字。因此,double范例通常可以包管15-17位有用数字的精度。
sqrt() 和 pow() 函数是 C 尺度库 <math.h> 中的两个紧张数学函数,其函数原型分别为:
- double sqrt(double x);
- double pow(double x, double y);
复制代码 sqrt()函数用于盘算x的平方根,而pow()函数用于盘算x的y次幂。这两个函数的参数和返回值范例均为double范例。
对于sqrt()函数,要求输入参数x必须好坏负实数。假如x为负数,在大多数实现中会产生域错误(domain error),并返回NaN(Not a Number)值。
现在,我们针对这两个函数与整数之间的关系提出以下两个标题:
- 1.当n是一个完全平方数时,使用sqrt(n)函数是否可以大概盘算出n的正确整数平方根?
- 2.使用pow()函数是否可以大概盘算出x^y的正确整数值?
- 注:本文中所讨论的"整数"一样平常是指在尺度整数范例可表现范围内的整数值。
1. 使用sqrt()是否可以得到完全平方数的正确的整数平方根
1.1 完全平方数的盘算效果是否正确?
完全平方数的平方根是整数(比方 sqrt(4)=2)。对于较小的完全平方数(如 4, 9, 16 等),双精度浮点数(double)可以正确表现它们的平方根,因此 sqrt() 函数会返回正确的整数值(如 2.0)。
1.2 为什么不会出现毛病(如 1.9999999)?
- 浮点数的特性:
双精度浮点数(double)的尾数有52位,可以正确表现全部绝对值小于 2^53(约 9e15)的整数。因此,对于较小的完全平方数(如 4, 100, 10000 等),其平方根是整数且落在 2^53 范围内,sqrt() 的效果会是正确的。
- 数学库的优化:
今世数学库(如 glibc)会对完全平方数的盘算举行优化,直接返回正确的整数值,制止浮点运算的舍入毛病。
1.3 大概产生毛病的情况
只有当完全平方数的平方根 高出双精度浮点数的正确表现范围 时,才会出现毛病。比方:
- 对于 n = (2^26)^2 = 2^52,其平方根 2^26 是正确的。
- 但对于 n = (2^26 + 1)^2,平方根 2^26 + 1 大概会因超出 2^53 的正确表现范围而产生微小毛病。
- 注:在实测中,没有产生毛病,都能正确表现。
1.4 总结
- 对于较小的完全平方数(如 4, 9, 100 等):
sqrt() 返回的效果是正确的(如 2.0, 3.0, 10.0),不会出现 1.9999999 或 2.00000000001。
- 对于极大的完全平方数(高出 2^53):
大概因浮点数精度限定产生微小毛病,需审慎处理惩罚。
<hr> 2. 使用pow函数盘算整数的幂能否得到正确的整数值
在C语言中,pow函数不能包管总是返回正确的整数值,其正确性取决于以下关键因素:
2.1 浮点数的精度限定
- pow函数的参数和返回值均为double范例,其底层使用浮点数运算。固然double范例可以正确表现肯定范围内的整数(通常到2⁵³),但当盘算效果超出此范围时,精度丢失大概导致毛病。
- 示例:
- printf("%.0f", pow(2, 53)); //输出 9007199254740992(精确)
- printf("%.0f", pow(2, 53)+1); //同样输出 9007199254740992(无法区分)
复制代码
2.2 隐式范例转换的陷阱
- 纵然输入的底数和指数是整数,pow内部仍会转换为浮点数盘算。对于某些看似简朴的运算,舍入毛病大概导致不测效果:
|