问题描述
嘿,我正在制作小型 C++ 程序来计算 sin(x) 的值直到小数点后 7 位,但是当我使用该程序计算 sin(PI/2) 时,它给了我 {{1} } 而不是 0.9999997
我该如何解决这个错误?
我知道为什么我要得到这个值作为输出,问题是我应该用什么方法来解决这个逻辑错误?
这是我的代码供参考
1.0000000
解决方法
我看到三个错误:
-
10e-7
是10*10^(-7)
,它似乎比您想要的大 10 倍。我想你想要1e-7
。 -
如果
t > 10e-7
仍然很大但为负值,则您的测试t
将变为假并退出循环。您可能需要abs(t) > 1e-7
。 要获得所需的准确度,您需要达到
n = 7
,这让您计算factorial(13)
,它溢出 32 位int
。 (如果使用 gcc,您可以使用-fsanitize=undefined
或-ftrapv
来捕捉它。)您可以通过使用至少 64 位的long long int
或int64_t
获得一些喘息空间。
sin(PI/2) ... 它给了我 0.9999997 而不是 1.0000000
对于 [-pi/4...+pi/4]
之外的值,泰勒正弦/余弦级数收敛缓慢,并且会受到项取消和 int factorial(int n)
** 溢出的影响。保持在甜蜜的范围内。
考虑使用触发属性 sin(x + pi/2) = cos(x)
、sin(x + pi) = -sin(x)
等将 x
带入 [-pi/4...+pi/4]
范围。
代码使用 remquo (ref2) 来查找商的余数和部分。
// Bring x into the -pi/4 ... pi/4 range (i.e. +/- 45 degrees)
// and then call owns own sin/cos function.
double my_wide_range_sin(double x) {
if (x < 0.0) {
return -my_sin(-x);
}
int quo;
double x90 = remquo(fabs(x),pi/2,&quo);
switch (quo % 4) {
case 0:
return sin_sweet_range(x90);
case 1:
return cos_sweet_range(x90);
case 2:
return sin_sweet_range(-x90);
case 3:
return -cos_sweet_range(x90);
}
return 0.0;
}
这意味着 OP 也需要编写一个 cos()
函数。
** 可以使用 long long
代替 int
来稍微扩展 int factorial(int n)
的有用范围,但这只会增加一些 x
。可以使用double
。
更好的方法是根本不使用 factorial()
,而是按 1.0/(n * (n+1))
等缩放每个连续项。