c - 当 float 是函数的实际参数时,为什么我的计算机会任意更改 float 末尾的小数位?

标签 c floating-point

我试图回答这个问题:编写一个函数 print_dig_float(float f) 打印 float f 的每个数字的值。例如,如果 f 为 2345.1234,则 print_dig_float(f) 将连续打印数字 2、3、4、5、1、2、3 和 4 的整数值。

我所做的是:给定一个带有一些小数的数字,我尝试通过将其乘以 10 来将数字向左移动(例如:3.45 -> 345)。之后,我将每个数字存储在一个数组中,方法是取其余部分并将其放入一个元素中。然后,我将它们打印出来。

所以我的程序是这样的:

#include <stdio.h>

void print_dig_float(float f);

int main(int argc, char const *argv[]) {

    print_dig_float(23432.214122);

    return 0;
}

void print_dig_float(float f) {

    printf("%f\n", f);

    int i = 0, arr[50], conv;

    //move digits to the left

    do {

        f = f * 10;
        conv = f;
        printf("%i\n", conv);

    } while (conv % 10 != 0);

    conv = f / 10;

    //store digits in an array

    while (conv > 1) {
        arr[i] = conv % 10;
        conv = conv / 10;
        i++;
    }

    for (int j = i - 1; j >= 0; j--) {
        printf("%i ", arr[j]);
    }

    printf("\n");

}

当我用数字测试它时:23432.214122,这是我得到的(根据 Linux 终端):

23432.214844

234322

2343221

23432216

234322160

2 3 4 3 2 2 1 6

问题是,正如您在上面看到的,甚至在我对它进行任何操作之前,计算机就任意更改了数字末尾的小数位。这个问题不知道是我的错还是电脑的错。

最佳答案

根据 C 2018 5.2.4.2.2, float 用符号、某个指数的固定基数以及由该基数中的数字组成的数字表示。最常见的是,二作为基数。

当基数为二时,23432.214122 不能用 float 表示,因为每个可表示的数字都必然是基数的幂(可能是负幂)的某个整数倍。 23432.214122 不是 ½、¼、⅛、1/24、1/25 或任何其他 2 的幂的倍数。

23432.214122 在源代码中使用时,它被转换为可表示的值。在良好的 C 实现中,使用最接近的可表示值,但 C 标准允许使用最接近的较大值或最接近的较小值的可表示值。除此之外,出现的数字不是任意的;它们是数学的结果。

当 IEEE-754 binary32 用于 float 时,最接近 23432.214122 的可表示值正好是 23432.21484375。

因为,当 C 实现对 float 使用基数 2 时, float 只有二进制数字,没有十进制数字。尝试从没有十进制数字的事物中提取十进制数字通常没有意义。可以确定原始数字中的十进制数字,直至达到受浮点格式影响的某个限制。但是,“23432.214122”的位数太多,无法使用 32 位浮点类型执行此操作。对于 64 位类型,如通常用于 double,您可以恢复原始数字,前提是您知道有多少位十进制数字开始。如果没有该信息,通常不可能恢复原始数字 - 正如您所见,尾随数字会有所不同,并且 float 本身没有指示差异开始的位置。

关于c - 当 float 是函数的实际参数时,为什么我的计算机会任意更改 float 末尾的小数位?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59212866/

相关文章:

c - C中的memcmp、strcmp和strncmp有什么区别?

c - 为什么 MSVS 不优化 +0?

python : Float addition causing problems in conditional statement

java - 使用 Java 迭代所有浮点值

c - 如何计算字符串中未知数量的 float

c - 动态阵列打印

c - 打印 B+ 树的键

c - malloc(0) 的行为

c - qsort const指针问题

c# - 将 byte[] 转换为数组问题