C 两个浮点数的划分给出了错误的答案
尝试使用以下代码在C中划分两个浮点:C 两个浮点数的划分给出了错误的答案,c,gcc,division,C,Gcc,Division,尝试使用以下代码在C中划分两个浮点: #include <stdio.h> #include <math.h> int main(){ float fpfd = 122.88e6; float flo = 10e10; float int_part, frac_part; int_part = (int)(flo/fpfd); frac_part = (flo/fpfd) - int_part; printf("\nInt_Part = %f
#include <stdio.h>
#include <math.h>
int main(){
float fpfd = 122.88e6;
float flo = 10e10;
float int_part, frac_part;
int_part = (int)(flo/fpfd);
frac_part = (flo/fpfd) - int_part;
printf("\nInt_Part = %f\n", int_part);
printf("Frac_Part = %f\n", frac_part);
return(0);
}
然后我得到这个输出:
Int_Part = 813.000000
Frac_Part = 0.802063
现在,这个分形部分似乎不正确。我先在计算器上试过同样的方程式,然后在Wolfram Alpha中试过,他们都给了我:
Frac_Part = 0.802083
请注意,小数点后第五位的数字是不同的
这对大多数人来说似乎无关紧要,但对于我正在做的计算来说,这是至关重要的
有人能给我解释一下为什么C代码会出现这种错误吗?
float
只有6~9个有效数字,对于大多数实际应用来说不够精确。将所有float
变量更改为double
(提供15~17个有效数字)将产生以下输出:
Int\u Part=813.000000
压裂部分=0.802083
当浮点运算的精度不足时,最自然的第一步是只使用精度更高的浮点类型,例如使用双精度而不是浮点。(正如其他答案中立即指出的。)
第二,考察不同的浮点运算,并考虑它们的精度。在我看来,一个突出的错误来源是上面的方法,通过简单地转换为int和减法,将浮点分为整数部分和小数部分。这并不理想,因为当你从原始值中减去整数部分时,你在做算术,其中涉及的三个数字(两个输入和结果)具有非常不同的比例,这可能会导致精度损失
我建议使用C
函数modf
将浮点数拆分为整数和小数部分
(更详细:当您执行类似f-(int)的操作时)f
,浮点加法过程将看到两个给定精度X的数字被相加,它自然会假设结果也有精度X。然后它将在该假设下执行实际计算,最后重新评估结果的精度。因为ial预测结果并不理想,一些低阶位将丢失。)浮点是单精度浮点,您应该尝试使用双精度,以下代码给出了正确的结果:
#include <stdio.h>
#include <math.h>
int main(){
double fpfd = 122.88e6;
double flo = 10e10;
double int_part, frac_part;
int_part = (int)(flo/fpfd);
frac_part = (flo/fpfd) - int_part;
printf("\nInt_Part = %f\n", int_part);
printf("Frac_Part = %f\n", frac_part);
return(0);
}
#包括
#包括
int main(){
双fpfd=122.88e6;
双flo=10e10;
双内件、压裂件;
int_部分=(int)(flo/fpfd);
压裂部分=(flo/fpfd)-内部部分;
printf(“\n部分=%f\n”,内部部分);
printf(“压裂部分=%f\n”,压裂部分);
返回(0);
}
为什么?
正如我所说,浮点是单精度浮点,它们比double小(在大多数体系结构中,sizeof(float)
)。
通过使用double
而不是float
,您将有更多的位来存储尾数和数字的指数部分(请参阅)。这不是C,而是标准浮点类型的属性。你认为什么可以用固定的位数来表示?做一些关于浮点(算术)的研究。你试过使用double
?时间到了。我认为这不是一个好的复制品。这个问题与一般的浮点精度问题无关。毕竟,在float
上使用double
仍然无法避免浮点精度问题,但它确实给出了预期的结果。“float
只有7个有效数字,在实际应用中不够精确。”我的意思是,这不是真的,对吗?它对于OpenGL来说已经足够了,而OpenGL在实际应用中肯定占很大一部分。它更像是,它通常不适合于数值实验/科学数据分析。@ChrisBeck 7是float
通常提供的。我已经编辑成更精确的版本。我仍然认为在大多数实际应用中不够精确的部分是正确的,在现代机器上,double
的算术通常比tfloat
快。注:C保证float
至少有6位小数精度<代码>双至少有10位十进制数字。对于C帖子:不是引用C++站点,而是从C++库<代码> CMASUD/COD>中建议函数<代码> MODFE()/CUT>,推荐C99函数<代码>浮点MODFF(浮点值,浮点*IPTR);代码>更有意义这是一个很好的观点,编辑了问题。奇怪的是,维基百科也提到了这一点:你的评论的ref IMO更好。当然,该标准是“最佳”的,但作为派生位置(如en.cppreference)并不容易理解。
#include <stdio.h>
#include <math.h>
int main(){
double fpfd = 122.88e6;
double flo = 10e10;
double int_part, frac_part;
int_part = (int)(flo/fpfd);
frac_part = (flo/fpfd) - int_part;
printf("\nInt_Part = %f\n", int_part);
printf("Frac_Part = %f\n", frac_part);
return(0);
}