为了好玩,我试图使用一系列扩展来评估从0到1的高斯积分。出于这个原因,我写了一个阶梯函数,它可以运行到20个!(我检查过)然后我写了这个:
int main(){
int n;
long double result=0;
for(n=0; n<=5; n++){
if(n%2==0){
result+=(((long double) 1/(long double)(factorial(n)*(2*n+1))));
} else {
result-=(((long double) 1/(long double)(factorial(n)*(2*n+1))));
}
}
printf("The Gaussian integral from 0 to 1 is %Lf\n", result);
}
这给了我一个奇怪的负数,显然不是很接近。我怀疑问题出在演员身上,但我不知道它是什么。有什么想法吗?这不是我尝试的第一件事。我尝试在表达式中转换任何内容并在开头放置显式转换,但它没有用。
答案 0 :(得分:3)
您使用的是MinGW编译器(Windows的gcc端口),它存在long double
类型的问题。这是由于GCC实施long double
和Microsoft的C库之间存在冲突。另请参阅this question。
根据this question,定义__USE_MINGW_ANSI_STDIO
可以解决此问题。如果没有,则使用double
代替。
答案 1 :(得分:2)
在(long double)(factorial(n)*(2*n+1)
中,乘法是整数乘法,如果factorial
的结果已经接近所用整数类型的限制,则第一个乘法可能会溢出。
写((long double)(factorial(n))*(2*n+1)
,以便第一次乘法是浮点乘法。
答案 2 :(得分:2)
您几乎肯定会溢出整数类型。在C中,这在技术上是未定义的行为。
对于32位无符号整数,13!会溢出来的。在64位,21!会溢出。
如果您使用浮点double
类型或类似__uint128
的扩展名(我认为,最多34个!),如果您的编译器支持它,您的算法将会存活一段时间。
您遇到的另一个问题是,您正在逐步添加缩小尺寸的条款。使用浮点类型时,这绝不是一个好主意。如果以相反的顺序运行for
循环,则结果将更准确。