如何在 C++ 中使用 arctanx 函数修复此错误
How do I fix this bug with arctanx function in c++
我的老师最近给了我一道题,题目是关于一些称为 arctanx 公式的数学方程式/公式。问题是:
According to the Arctanx(x) = x - ((x ^ 3) / 3) + ((x ^ 5) / 5) - ((x ^
7) / 7) + ...and π = 6 * arctanx(1 / sqrt(3)), Create function arctanx(x)
, and find pi when the last "number"(like this ((x ^ y) / y)) is right before
and bigger than 10 ^ -6, or you can say that no "number" can be smaller than
that number without being smaller than 10 ^ -6.
我试着把它编码出来,但是里面有一个错误。
# include<iostream>
# include<math.h>
using namespace std;
float arctanx() {
long double pi = 3.1415926535897;
int i = 0; // 0 = +, 1 = -
float sum = 0;
float lsum;
for (int y = 1; y < pi; y += 2) {
if (lsum > 0.000001) {
if (i == 0) {
lsum = pow(1 / sqrt(3), y) / y;
sum += pow(1 / sqrt(3), y) / y;
i++;
} else if (i == 1) {
lsum = pow(1 / sqrt(3), y) / y;
sum -= pow(1 / sqrt(3), y) / y;
i--;
}
} else {
break;
}
}
sum = sum * 6;
return sum;
}
int main() {
cout << arctanx();
return 0;
}
它应该有一些不等于零的数字的输出,但我从 运行 中得到了 0。
您的程序存在未定义行为,因为您在比较 if (lsum > 0.000001)
中使用了未初始化的 float lsum;
。
在你的情况下可能发生的情况是 lsum
恰好小于或等于 0.000001
并且你的 for
立即 break
s 而没有做任何导致你的函数 return 0 * 6
这显然是 0
.
Create function arctanx(x)
发布的代码中定义的函数不接受任何参数,它仅使用硬连线(和重复)值 1 / sqrt(3)
并尝试 return π 的近似值而不是x 的反正切。
它也有未定义的行为,当它首次用于循环内的比较时 lsum
未初始化(因此具有不确定的值)。
考虑这个实现,但请注意,这个特定的多项式展开对于大于 1 的 x 值发散。
#include <iostream>
#include <iomanip>
#include <cmath>
double arctanx(double x);
int main()
{
double pi = 6.0 * arctanx(1.0 / std::sqrt(3));
std::cout << std::setprecision(8) << pi << '\n';
}
double arctanx(double x)
{
// You can take advantage of a running power, instad of calculating
// pow(x, i) at every iteration
double sq_x = x * x;
double pow_x = x * sq_x;
double err = 1e-6;
// Instead of keeping track of the alternating sign, you can use
// two separate partial sums
double sum_pos_term = x;
double sum_neg_term = 0.0;
for (int i = 3; i < 33; i += 2) // <- Limit the number of iterations
{
if (pow_x < err * i)
break;
sum_neg_term += pow_x / i;
i += 2;
pow_x *= sq_x;
if (pow_x < err * i)
break;
sum_pos_term += pow_x / i;
pow_x *= sq_x;
}
return sum_pos_term - sum_neg_term;
}
我的老师最近给了我一道题,题目是关于一些称为 arctanx 公式的数学方程式/公式。问题是:
According to the Arctanx(x) = x - ((x ^ 3) / 3) + ((x ^ 5) / 5) - ((x ^
7) / 7) + ...and π = 6 * arctanx(1 / sqrt(3)), Create function arctanx(x)
, and find pi when the last "number"(like this ((x ^ y) / y)) is right before
and bigger than 10 ^ -6, or you can say that no "number" can be smaller than
that number without being smaller than 10 ^ -6.
我试着把它编码出来,但是里面有一个错误。
# include<iostream>
# include<math.h>
using namespace std;
float arctanx() {
long double pi = 3.1415926535897;
int i = 0; // 0 = +, 1 = -
float sum = 0;
float lsum;
for (int y = 1; y < pi; y += 2) {
if (lsum > 0.000001) {
if (i == 0) {
lsum = pow(1 / sqrt(3), y) / y;
sum += pow(1 / sqrt(3), y) / y;
i++;
} else if (i == 1) {
lsum = pow(1 / sqrt(3), y) / y;
sum -= pow(1 / sqrt(3), y) / y;
i--;
}
} else {
break;
}
}
sum = sum * 6;
return sum;
}
int main() {
cout << arctanx();
return 0;
}
它应该有一些不等于零的数字的输出,但我从 运行 中得到了 0。
您的程序存在未定义行为,因为您在比较 if (lsum > 0.000001)
中使用了未初始化的 float lsum;
。
在你的情况下可能发生的情况是 lsum
恰好小于或等于 0.000001
并且你的 for
立即 break
s 而没有做任何导致你的函数 return 0 * 6
这显然是 0
.
Create function arctanx(x)
发布的代码中定义的函数不接受任何参数,它仅使用硬连线(和重复)值 1 / sqrt(3)
并尝试 return π 的近似值而不是x 的反正切。
它也有未定义的行为,当它首次用于循环内的比较时 lsum
未初始化(因此具有不确定的值)。
考虑这个实现,但请注意,这个特定的多项式展开对于大于 1 的 x 值发散。
#include <iostream>
#include <iomanip>
#include <cmath>
double arctanx(double x);
int main()
{
double pi = 6.0 * arctanx(1.0 / std::sqrt(3));
std::cout << std::setprecision(8) << pi << '\n';
}
double arctanx(double x)
{
// You can take advantage of a running power, instad of calculating
// pow(x, i) at every iteration
double sq_x = x * x;
double pow_x = x * sq_x;
double err = 1e-6;
// Instead of keeping track of the alternating sign, you can use
// two separate partial sums
double sum_pos_term = x;
double sum_neg_term = 0.0;
for (int i = 3; i < 33; i += 2) // <- Limit the number of iterations
{
if (pow_x < err * i)
break;
sum_neg_term += pow_x / i;
i += 2;
pow_x *= sq_x;
if (pow_x < err * i)
break;
sum_pos_term += pow_x / i;
pow_x *= sq_x;
}
return sum_pos_term - sum_neg_term;
}