为什么浮点数不能给出期望的答案? 嘿,我正在制作小的C++程序来计算正弦(x)的值直到7个小数点,但是当我计算正弦(pi/2)< /强>时,使用这个程序,它给我 0×999999<7 /代码>而不是 1 0000000 < /COD>如何解决这个错误? 我知道为什么要把这个值作为输出,问题是我应该用什么方法来解决这个逻辑错误

为什么浮点数不能给出期望的答案? 嘿,我正在制作小的C++程序来计算正弦(x)的值直到7个小数点,但是当我计算正弦(pi/2)< /强>时,使用这个程序,它给我 0×999999<7 /代码>而不是 1 0000000 < /COD>如何解决这个错误? 我知道为什么要把这个值作为输出,问题是我应该用什么方法来解决这个逻辑错误,c++,floating-point,precision,floating-accuracy,C++,Floating Point,Precision,Floating Accuracy,这是我的代码供参考 #包括 #包括 #定义PI 3.1415926535897932384626433832795 使用名称空间std; 双sin(双x); 整数阶乘(intn); 双倍功率(双倍a,整数b); int main() { 双x=PI/2; 我可以看到三个错误: 10e-7是10*10^(-7)它似乎比你想要的大10倍。我想你想要1e-7 您的测试t>10e-7将变为假,如果t仍然很大但为负数,则退出循环。您可能需要abs(t)>1e-7 要获得所需的精度,您需要达到n=7,

这是我的代码供参考

#包括
#包括
#定义PI 3.1415926535897932384626433832795
使用名称空间std;
双sin(双x);
整数阶乘(intn);
双倍功率(双倍a,整数b);
int main()
{
双x=PI/2;
我可以看到三个错误:

  • 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.999997,而不是1.0000000

对于
[-pi/4…+pi/4]
之外的值,泰勒的sin/cos级数收敛缓慢,并且会出现项的取消和
int阶乘(int n)
**的溢出。请保持在最佳范围内

考虑使用触发器属性
sin(x+pi/2)=cos(x)
sin(x+pi)=-sin(x)
等将
x
引入
[-pi/4…+pi/4]
范围

代码使用()查找商的余数和部分

//将x置于-pi/4…pi/4范围内(即+/-45度)
//然后调用自己的sin/cos函数。
双倍my\u wide\u range\u sin(双倍x){
if(x<0.0){
return-my_sin(-x);
}
现状;
双x90=remquo(晶圆厂(x),π/2,&quo);
交换机(quo%4){
案例0:
返回sin_sweet_范围(x90);
案例1:
返回cos_sweet_范围(x90);
案例2:
返回正弦范围(-x90);
案例3:
返回-cos_sweet_范围(x90);
}
返回0.0;
}
这意味着OP也需要编写一个
cos()
函数


**可以使用
long-long
而不是
int
略微扩展
int阶乘(int n)
的有用范围,但这只会增加一些
x
。可以使用
double


更好的方法根本不使用
factorial()
,而是通过
1.0/(n*(n+1))对每个连续项进行缩放
或诸如此类。

我不明白第二个错误。为什么它会为负值为真?@setller:对不起,我倒着说了,现在修好了。正是因为这个原因,我连续读了两个术语。@setller:当
x
很大时,它没有帮助。想想
x=5
例如,前两个术语的总和是一个很大的负数。我同意它不会对
x=PI/2
造成问题,但它仍然是一个bug。你能给出解释或提供链接来理解remquo的功能吗?另请参见@mAlters添加了额外的好参考。@user207421:请不要随意关闭与该问题重复的浮点问题。pr这里的问题是由于整数运算中的错误;
int factorial(int)
函数溢出,将其更改为
double factorial(int)
会导致程序产生所需的输出“1”。跳到包含浮点代码的程序是错误的结论,因为浮点行为是错误的。
#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);
    }
}
// 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;
}