对于较大和较小的值,相同的操作似乎工作方式不同(我认为下面的代码比我用文字更好地解释了这个问题),我以相同的方式计算了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 = %fn", max, max2);
int max3 = ceil((float) 3 / 2);
float max4 = ((float) 3) / 2;
printf("ma3 = %i, max4 = %fn", max3, max4);
}
输出:
max = 1812441, max2 = 1812441.000000
ma3 = 2, max4 = 1.500000
我期望max = 1812442, max2 = 1812441.062500是输出,因为这是原则上应该是什么。现在我不知道该怎么办了
浮点C除法
这个问题与除法无关。在初始转换为float
时出现舍入误差。
在float
, IEEE-754 binary32中最常用的格式中,接近86,997,171的两个可表示的数字是86,997,168和86,997,176。(这些是10,874,746•23和10,874,747•103。10,874,746和10,874,747是24位数字(在二进制中需要24位数字来表示它们),24位是binary32格式用于表示浮点数的分数部分的全部。
两者中,86,997,168更接近。因此,在(float) 86997171
中,86,997,171被转换为86,997,168。
则86,997,168/48 = 1,812,441。所以(float) 86997171 / 48
是1,812,441,ceil((float) 86997171 / 48)
也是。因此,max
和max2
都设置为1,812,441。
在C语言中,float
是一种单精度浮点格式,所以它通常是4字节(在大多数编译器上),所以它的精度大约是6-9位有效数字,通常是7位。
您的问题号码,1812441.0625
有11位数字,不适合float
类型。
您应该使用double
,它在C中是双精度浮点格式,所以它通常是8字节(在大多数编译器上),所以它的精度大约是15-18位有效数字,通常是16位,因此可以保持您的数字的精度。
实际上,在这种情况下使用double
会得到:
max = 1812442, max2 = 1812441.062500
ma3 = 2, max4 = 1.500000
这是你需要的。
链接到代码。
注意,这里解释了这些类型的精度。这与事实相去甚远(正如链接所解释的那样),但它为你的问题提供了很好的视角。