求 0 到 125 之间数字的立方根

Ahm*_*rek 3 c precision cubic

我正在尝试编写一个函数的 C 代码,该函数接受一个整数从0to125并仅当它是整数( 1,2,3,4,5 )时才返回该整数的立方根,如果不是整数,0则返回。所以我写了这段代码:

unsigned int cubic(unsigned int n) {
    if (n > 125)
        return 0;
    double root = pow(n, (1 / 3.));
    double rem = (double)(roundf(root)) - root;
    if (rem != 0)
        return 0;
    else
       return roundf(root);
}
Run Code Online (Sandbox Code Playgroud)

此函数适用于除 number64和之外的所有情况125。在这些情况下,它返回的0不是这些数字的立方根,分别是45。有人可以向我解释为什么会发生这种情况吗?

chq*_*lie 5

由于1 / 3.无法准确地表示为浮点数,浮点计算pow(64, (1 / 3.))可能会产生一个非常接近 的数字4,但稍小或稍大,足以4(double)(roundf(root)) - root不同0

您可以通过以下方式解决此精度问题:

unsigned int cubic(unsigned int n) {
    int root = (int)round(pow(n, 1 / 3.));
    if (root * root * root == n)
        return root;
    else
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果您的系统上可用pow(n, 1 / 3.),您可以使用 代替cbrt(n),但精度问题可能仍然存在。

对于您的目标,迭代可能的整数根并检查似乎要简单得多:

unsigned int cubic(unsigned int n) {
    for (unsigned int i = 1; i <= 5; i++) {
        unsigned int i3 = i * i * i;
        if (i3 == n)
            return i;
        if (i3 > n)
            break;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

或者更明确地说:

unsigned int cubic(unsigned int n) {
    switch (n) {
      case 1 * 1 * 1: return 1;
      case 2 * 2 * 2: return 2;
      case 3 * 3 * 3: return 3;
      case 4 * 4 * 4: return 4;
      case 5 * 5 * 5: return 5;
      default: return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)