簡體   English   中英

為什么浮點數沒有給出想要的答案?

[英]why floating point numbers does not give desired answer?

嘿,我正在制作小型 C++ 程序來計算 sin(x) 的值直到小數點后 7 位,但是當我使用這個程序計算sin(PI/2)時,它給了我0.9999997而不是1.0000000我該如何解決這個錯誤? 我知道為什么我得到這個值是 output,問題是我應該用什么方法來解決這個邏輯錯誤?

這是我的參考代碼

#include <iostream>
#include <iomanip>
#define PI 3.1415926535897932384626433832795
using namespace std;

double sin(double x);
int factorial(int n);
double Pow(double a, int b);

int main()
{
    double x = PI / 2;
    cout << setprecision(7)<< sin(x);
    return 0;
}

double sin(double x)
{
    int n = 1;      //counter for odd powers.
    double Sum = 0; // to store every individual expression.
    double t = 1;   // temp variable to store individual expression
    for ( n = 1; t > 10e-7; Sum += t, n = n + 2)
    {
        // here i have calculated two terms at a time because addition of two consecutive terms is always less than 1.
        t = (Pow(-1.00, n + 1) * Pow(x, (2 * n) - 1) / factorial((2 * n) - 1))
            +
            (Pow(-1.00, n + 2) * Pow(x, (2 * (n+1)) - 1) / factorial((2 * (n+1)) - 1));
    }

    return Sum;
}
int factorial(int n)
{
    if (n < 2)
    {
        return 1;
    }
    else
    {
        return n * factorial(n - 1);
    }
}
double Pow(double a, int b)
{
    if (b == 1)
    {
        return a;
    }
    else
    {
        return a * Pow(a, b - 1);
    }
}

我看到三個錯誤:

  • 10e-710*10^(-7) ,它似乎比你想要的大 10 倍。 我想你想要1e-7

  • 如果t仍然很大但為負,您的測試t > 10e-7將變為假,並退出循環。 您可能需要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]之外的值,泰勒的 sin/cos 級數收斂緩慢,並且會遭受項的取消和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() function。


**可以使用long long而不是int來稍微擴展int factorial(int n)的有用范圍,但這只會增加一些x 可以使用double

更好的方法根本不使用factorial() ,而是將每個連續項縮放1.0/(n * (n+1))等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM