编写自己的数学楼层函数C的实现

dar*_*ias 7 c math floor

我正在考虑floor可用的功能math.h.它很容易使用:

#include <stdio.h>
#include <math.h>

int main(void)
{
  for (double a = 12.5; a < 13.4; a += 0.1)
    printf("floor of  %.1lf is  %.1lf\n", a, floor(a));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我想编写自己的实现怎么办?看起来像这样:

#include <stdio.h>
#include <math.h>

double my_floor(double num)
{
    return (int)num;
}

int main(void)
{
    double a;

    for (a = 12.5; a < 13.4; a += 0.1)
        printf("floor of  %.1lf is  %.1lf\n", a, floor(a));

    printf("\n\n");

    for (a = 12.5; a < 13.4; a += 0.1)
        printf("floor of  %.1lf is  %.1lf\n", a, my_floor(a));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它似乎不适用于负数(my_floor),但第二个看起来很好(my_floor_2):

#include <stdio.h>
#include <math.h>

double my_floor(double num)
{
    return (int)num;
}

double my_floor_2(double num)
{
    if(num < 0)
        return (int)num - 1;
    else
        return (int)num;
}

int main(void)
{
    double a1 = -12.5;

    printf("%lf\n", floor(a1));
    printf("%lf\n", my_floor(a1));
    printf("%lf\n", my_floor_2(a1));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

程序输出:

IMG

其中一个最终是否正确?

chq*_*lie 7

您的两种尝试都有局限性:

  • 如果double值超出类型的范围int,则转换为int实现定义的。
  • 如果该double值为负数但为整数,则返回(int)num - 1不正确。

这是一个(几乎)可移植的版本,尝试处理所有情况:

double my_floor_2(double num) {
    if (num >= LLONG_MAX || num <= LLONG_MIN || num != num) {
        /* handle large values, infinities and nan */
        return num;
    }
    long long n = (long long)num;
    double d = (double)n;
    if (d == num || num >= 0)
        return d;
    else
        return d - 1;
}
Run Code Online (Sandbox Code Playgroud)

long long如果 type 的值位多于 type ,那么它应该是正确的(double大多数现代系统都是这种情况)。


Bat*_*eba 5

不,你不能这样解决它.编写自己的实现的最佳方法是从平台上的C标准库中窃取一个.但请注意,可能包含特定于平台的细微差别,因此可能无法移植.

C标准库floor函数通常很聪明,因为它不能通过转换为整数类型来工作.如果确实如此,那么您将面临signed整数溢出的风险,其行为未定义.(请注意,a的最小可能范围int是-32767到+32767).

精确实现还取决于平台上使用的浮点方案.

对于使用IEEE754浮点的平台和long long类型,您可以采用此方案:

  1. 如果数字的大小大于2的53次方,则将其返回(因为它已经是整数).
  2. 否则,转换为64位类型(长很长),并将其返回.