为什么浮点数没有给出想要的答案?

问题描述

嘿,我正在制作小型 C++ 程序来计算 sin(x) 的值直到小数点后 7 位,但是当我使用该程序计算 sin(PI/2) 时,它给了我 {{1} } 而不是 0.9999997 我该如何解决这个错误? 我知道为什么我要得到这个值作为输出,问题是我应该用什么方法解决这个逻辑错误

这是我的代码供参考

1.0000000

解决方法

我看到三个错误:

  • 10e-710*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 intint64_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)) 等缩放每个连续项。