C 中的浮点除法用于大数

float division in C for large numbers

提问人:RubyShanks 提问时间:12/18/2022 最后编辑:Tom KarzesRubyShanks 更新时间:12/19/2022 访问量:131

问:

对于更大和更小的值,相同的操作似乎以不同的方式工作(我认为下面的代码比我用文字更好地解释了这个问题)我以相同的方式计算了 max 和 max3,只是值不同。同样,我以完全相同的方式计算了 max2 和 max4 的不同值。然而,我得到的答案却大不相同?

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

int main(void)
{
    // 86997171 / 48 = 1812441.0625
    int max = ceil((float) 86997171 / 48);
    float max2 = ((float) 86997171)/ 48;
    printf("max = %i, max2 = %f\n", max, max2);
    int max3 = ceil((float) 3 / 2);
    float max4 = ((float) 3) / 2;
    printf("ma3 = %i, max4 = %f\n", max3, max4);
}

输出:

max = 1812441, max2 = 1812441.000000
ma3 = 2, max4 = 1.500000

我期望 max = 1812442,max2 = 1812441.062500 是输出,因为原则上应该是这样。现在我不知道该怎么办

C 铸造 浮点 除法

评论

1赞 Henry Ecker 12/18/2022
评论不用于扩展讨论;此对话已移至 Chat

答:

1赞 justANewb stands with Ukraine 12/18/2022 #1

在 C 中,是一种单精度浮点格式,因此它通常是 4 个字节(在大多数编译器上),因此其精度约为 6-9 位有效数字,通常为 7 位。float

您的相关号码有 11 位数字,不适合类型。1812441.0625float

你应该改用它,它在 C 中是一种双精度浮点格式,所以它通常是 8 个字节(在大多数编译器上),所以它的精度在 15-18 位有效数字左右,通常为 16 位,因此可以保持数字的精度。double

事实上,在这种情况下使用可以:double

max = 1812442, max2 = 1812441.062500
ma3 = 2, max4 = 1.500000

这就是你需要的。

代码链接


请注意,此处介绍了这些类型的精度。这与事实相去甚远(如链接所解释的那样),但它为您的问题提供了很好的视角。

评论

0赞 Eric Postpischil 12/18/2022
说有“6-9 位有效数字”是荒谬和错误的float
2赞 Eric Postpischil 12/19/2022 #2

C 中的浮点除法用于大数

这个问题与分裂无关。舍入错误发生在初始转换为 时。float

在最常用的格式 IEEE-754 二进制 32 中,接近 86,997,171 的两个可表示数字是 86,997,168 和 86,997,176。(它们是 10,874,746•2 3 和 10,874,747•103。10,874,746 和 10,874,747 是 24 位数字(二进制需要 24 位数字来表示它们),而 24 位是 binary32 格式用于表示浮点数的小数部分的全部内容。float

在这两者中,86,997,168 更接近。因此,在 中,86,997,171 转换为 86,997,168。(float) 86997171

那么 86,997,168 / 48 是 1,812,441。1,812,441 也是如此,.因此,两者都设置为 1,812,441。(float) 86997171 / 48ceil((float) 86997171 / 48)maxmax2