在计算cpp中数字的n次方根时,答案错误

Wrong answer while calculating the nth root of number in cpp

本文关键字:方根时 答案 错误 计算 cpp 数字      更新时间:2023-10-16

我正在使用标准库方法pow()计算正整数的n次方根。下面是我的程序片段:

double x,y;
x=pow(64,(1.0/3));
int z;
printf("x=%lfn",x);
z=(int)x;
printf("%dn",z);

但是在求64的立方根时。X打印为4000000,而z打印为3。为什么?

有谁能提出一个更好的算法吗?

如果您在x上打印更多数字,您将看到问题所在(我随机选择了30):

double x ;
x = pow(64, 1.0/3);
printf("x=%.30lfn",x);
输出:

x=3.99999999...999600000000 

显然,如果你把x变成int,它就会变成3

没有"完美"的解决方案。如果你只处理整数,你可以创建你自己的根函数,但如果你想要能够使用浮点数,你需要处理由于浮点表示而导致的精度问题。

也许有一些C库可以帮助你解决这类问题。

int覆盖向下舍入。由于浮点运算是不准确的,计算结果可能是3.999999…

使用round(x)得到正确的结果

由于您总是希望将向下舍入,因此您可以同时使用floor(int)——但是,一旦浮点计算的不稳定性导致值稍微减小,您就会遇到观察到的错误——对于double大小的计算,值大约为10-15。使用一个很小的epsilon值来抵消它。

请注意,下面的epsilon"fudge"值将与原始数字中的有效位数相关。对于较大的数,需要较小的

#include <stdio.h>
#include <string.h>
#include <math.h>
int main (void)
{
    double x;
    int z;
    x=pow(64,(1.0/3));
    printf("x=%lfn",x);
    printf("x=%.30lfn",x);
    z=(int)x;
    printf("%dn",z);
    z=(int)(x+0.000000000000005);
    printf("%dn",z);
    x=pow(64,(1.0/4));
    printf("x=%lfn",x);
    printf("x=%.30lfn",x);
    z=(int)x;
    printf("%dn",z);
    z=(int)(x+0.0000000000000005);
    printf("%dn",z);
    return 1;
}

中1/3和1/4次幂的结果
x=4.000000
x=3.999999999999999555910790149937
3
4
x=2.828427
x=2.828427124746190290949243717478
2
2

@jongware告诉int override向下舍入和浮点运算可能不准确。

尽管你总是可以这样做来避免这个问题

def invpow ( n , i):
    x = pow (n ,(1/i))
    if((int)pow((x+1) , i) <= n):
        x += 1;
    print(x)

或者你可以用这里和这里描述的牛顿-拉夫森法来写你自己的求幂方法

你也可以使用二进制搜索,如果你对范围有正确的猜测,这是相当快的(变量high和low)

def invpow( x, n, low, high){
    if(n==1)
        return x;
    mid=(low+high)/2;
    while(low<high){
        mid=(low+high)/2;
        raised=pw(mid,n);
        if(raised==x)
            break;
        if(raised>x)
            high=mid;
        else
            low=mid;
        if(low+1==high){
            mid=low;
            break;
            }
    }
    return mid;
}
相关文章: