提问人:RubyShanks 提问时间:12/18/2022 最后编辑:Tom KarzesRubyShanks 更新时间:12/19/2022 访问量:131
C 中的浮点除法用于大数
float division in C for large numbers
问:
对于更大和更小的值,相同的操作似乎以不同的方式工作(我认为下面的代码比我用文字更好地解释了这个问题)我以相同的方式计算了 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 中,是一种单精度浮点格式,因此它通常是 4 个字节(在大多数编译器上),因此其精度约为 6-9 位有效数字,通常为 7 位。float
您的相关号码有 11 位数字,不适合类型。1812441.0625
float
你应该改用它,它在 C 中是一种双精度浮点格式,所以它通常是 8 个字节(在大多数编译器上),所以它的精度在 15-18 位有效数字左右,通常为 16 位,因此可以保持数字的精度。double
事实上,在这种情况下使用可以:double
max = 1812442, max2 = 1812441.062500
ma3 = 2, max4 = 1.500000
这就是你需要的。
代码链接。
请注意,此处介绍了这些类型的精度。这与事实相去甚远(如链接所解释的那样),但它为您的问题提供了很好的视角。
评论
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 / 48
ceil((float) 86997171 / 48)
max
max2
评论