描述
计算一个浮点数的立方根,不使用库函数。
保留一位小数。
数据范围:∣val∣≤20
输入描述:
待求解参数,为double类型(一个实数)
输出描述:
输出参数的立方根。保留一位小数。
示例1
输入:
19.9
输出:
2.7
示例2
输入:
2.7
输出:
1.4
解题思路:
题目明确要求不能使用库函数,所以不能使用pow函数
因为题目输入的数val比较小,绝对值不大于20,且立方根保留一位小数,所以我们可以这么做:
准备工作:先判断val是正数还是负数或是0,若是0,直接打印其立方根为0就行,如果是负数,我们可以将flag置为-1(flag初始化为1),并将该负数乘-1转换成正数,按照这个正数来求立方根,最后乘flag即可,比如输入值val为-8,我们将flag由1改为-1,并将输入值val乘-1得到8,算出8的立方根为2,最后打印的时候乘flag就得到-2,如果是正数,则不用改变flag(1),求出其立方根后乘flag也不影响,那么问题的关键来了,在不调用库函数的前提下,如何求一个正数的立方根?
由于输入值val的绝对值不大于20,显然其立方根不大于3(3³为27),那么我们首先判断val(转换成正数后)的值,如果其小于1,那么其立方根的范围是在0,0.1,0.2,0.3.......1.0,我们可以求出这些立方根的立方,再求出此立方值与输入值的误差,其中误差最小的就是立方根了。同理,如果val大于1小于8,那它的立方根就是在1.0,1.1,1.2,1.3.......2.0之间的某个数,该数的立方与输入值是最接近的。
用题目的示例说明一下,如果输入值是19.9,因为其大于8(2³),所以其立方根就是2.0,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,3.0中的某个数,该数的立方与19.9是最接近的,以下附上它们的立方分别与19.9的误差(负的误差已转成正的):
很显然,当数为2.7时,2.7³与19.9的误差是最小的,仅为0.217,所以它就是19.9在保留1位小数时的立方根。
以下为代码:
#include <stdio.h>
int main()
{
double val,err[11],base,i;
char flag,k,min_err;
while(scanf("%lf",&val)!=EOF)
{
flag=1; //flag记录输入值是正数还是负数,1表示正数,-1表示为负数
if(val==0)
{
printf("0.0");
continue;
}
else if(val<0)
{
flag=-1; //val为负数,flag置为-1,将val转成正数,更好求其立方根
val*=-1;
}
if(val<1)
base=0; //val小于1,则立方根不大于1
else if(val<8)
base=1; //val小于8,立方根不大于2
else
base=2; //val大于等于8,小于20,立方根不大于3
for(i=0,k=0;i<=1;i+=0.1,k++)
{
err[k]=val-(base+i)*(base+i)*(base+i); //每次在base基础上加0.1,算出其立方
if(err[k]<0) //与输入值val的误差,并全转换为正
err[k]*=-1;
}
min_err=0;
for(k=1;k<11;k++)
{
if(err[min_err]>err[k]) //找到误差最小值的下标
min_err=k;
}
printf("%.1lf\n",flag*(base+min_err*0.1));
}
return 0;
}