为什么浮点数没有给出想要的答案?
why floating point numbers does not give desired answer?
嘿,我正在制作一个小的 C++ 程序来计算 sin(x) 的值,直到小数点后 7 位,但是当我使用这个程序计算 sin(PI/2) 时它给了我 0.9999997
而不是 1.0000000
我该如何解决这个错误?
我知道一点为什么我得到这个值作为输出,问题是我应该用什么方法来解决这个逻辑错误?
这是我的代码供参考
#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-7
是 10*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 int
或 int64_t
来获得一些喘息的空间。 =23=]
sin(PI/2) ... it gives me 0.9999997 rather than 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()
函数。
** 可以使用 long long
而不是 int
来略微扩展 int factorial(int n)
的有用范围,但这只会增加一些 x
。可以使用 double
.
更好的方法是根本不使用 factorial()
,而是将每个连续的项缩放 1.0/(n * (n+1))
等。
嘿,我正在制作一个小的 C++ 程序来计算 sin(x) 的值,直到小数点后 7 位,但是当我使用这个程序计算 sin(PI/2) 时它给了我 0.9999997
而不是 1.0000000
我该如何解决这个错误?
我知道一点为什么我得到这个值作为输出,问题是我应该用什么方法来解决这个逻辑错误?
这是我的代码供参考
#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-7
是10*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 int
或int64_t
来获得一些喘息的空间。 =23=]
sin(PI/2) ... it gives me 0.9999997 rather than 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()
函数。
** 可以使用 long long
而不是 int
来略微扩展 int factorial(int n)
的有用范围,但这只会增加一些 x
。可以使用 double
.
更好的方法是根本不使用 factorial()
,而是将每个连续的项缩放 1.0/(n * (n+1))
等。