做一个学校项目。我不明白为什么在-NaN
和sin(90)
之后,cos(120)
犯了罪。
任何人都可以帮我理解这个吗?
另外,当我把它放在在线C ++编辑器中时,它完全有效,但是当在linux中编译它时却没有。
// Nick Garver
// taylorSeries
// taylorSeries.cpp
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
const double PI = atan(1.0)*4.0;
double angle_in_degrees = 0;
double radians = 0;
double degreesToRadians(double d);
double factorial(double factorial);
double mySine(double x);
double myCosine(double x);
int main()
{
cout << "\033[2J\033[1;1H";
cout.width(4); cout << left << "Deg";
cout.width(9); cout << left << "Radians";
cout.width(11); cout << left << "RealSine";
cout.width(11); cout << left << "MySin";
cout.width(12); cout << left << "RealCos";
cout.width(11); cout << left << "MyCos"<<endl;
while (angle_in_degrees <= 360) //radian equivalent of 45 degrees
{
double sine = sin(degreesToRadians(angle_in_degrees));
double cosine = cos(degreesToRadians(angle_in_degrees));
//output
cout.width(4); cout << left << angle_in_degrees;
cout.width(9); cout << left << degreesToRadians(angle_in_degrees);
cout.width(11); cout << left << sine;
cout.width(11); cout << left << mySine(degreesToRadians(angle_in_degrees));
cout.width(12); cout << left << cosine;
cout.width(11); cout << left << myCosine(degreesToRadians(angle_in_degrees))<<endl;
angle_in_degrees = angle_in_degrees + 15;
}
cout << endl;
return 0;
}
double degreesToRadians(double d)
{
double answer;
answer = (d*PI)/180;
return answer;
}
double mySine(double x)
{
double result = 0;
for(int i = 1; i <= 1000; i++) {
if (i % 2 == 1)
result += pow(x, i * 2 - 1) / factorial(i * 2 - 1);
else
result -= pow(x, i * 2 - 1) / factorial(i * 2 - 1);
}
return result;
}
double myCosine(double x)
{
double positive = 0.0;
double negative= 0.0;
double result=0.0;
for (int i=4; i<=1000; i+=4)
{
positive = positive + (pow(x,i) / factorial (i));
}
for (int i=2; i<=1000; i+=4)
{
negative = negative + (pow(x,i) / factorial (i));
}
result = (1 - (negative) + (positive));
return result;
}
double factorial(double factorial)
{
float x = 1;
for (float counter = 1; counter <= factorial; counter++)
{
x = x * counter;
}
return x;
}
答案 0 :(得分:2)
(马库斯有好点;我会在其他方向漫步......)
查看泰勒系列中的术语。在不到10个学期之后,它们变得太小而不会产生任何差异。要求1000就是在寻找麻烦。
而不是去1000,直到下一学期不添加任何内容,例如:
term = pow(x, i * 2 - 1) / factorial(i * 2 - 1);
if (result + term == result) { break; }
result += term;
如果您迭代计算pow
和factorial
而不是每次都重复计算,那么该系列会运行得更快。 (但是,此时速度可能不是问题。)
Float具有24位二进制精度。也许从13开始!你会得到浮点数的舍入错误。另一方面,Double有53位精度,将持续到22左右!没有舍入错误。我的观点是你应该在double中完成factorial()。
另一个问题是泰勒级数的计算有些“不稳定”。更大的争论。中间项比最终结果大,从而导致其他舍入误差。为避免这种情况,计算正弦和余弦的常用方法是先折叠到-45到+45度之间。以后不需要展开,除了标志之外。
至于为什么你在一个系统上遇到麻烦而在另一个系统上遇到麻烦 - 不同的实现以不同的方式处理NaN。
一旦你完成了NaN,尝试以相反的顺序计算系列。这将导致一组不同的舍入误差。它会使你的罪()更接近真正的罪吗?
真实的&#39; sin可能是用64位定点算法在硬件中计算的,并且将被正确舍入&#34;超过99%的时间到53或24位。 (当然,这取决于芯片制造商,因此我的“挥手”声明。)
判断&#39;关闭&#39;你的价值是,你需要计算ULP(最后一个单位)。这涉及查看float / double中的位。 (超出了这个问题的范围。)
对TMI感到抱歉。
答案 1 :(得分:1)
在我回答这个问题之前,请注意几点:
double
作为输入并返回double
,但内部只使用float
;那应该是一面红旗!degreesToRadians
return (d*PI)/180;
会更好阅读,只有三分之一
现在回答:
在factorial
函数中,您可以计算最多1999
的值的阶乘。提示:尝试找出 1999!的值,并查找计算机上float
可以容纳的最大数量。然后查找double
的最大值。 1999多少个数量级!更大?
1999年!是约10 ^ 5732。这是一个很大的数字,比32位浮点数能够容纳的 150个数量级,或者仍然比64位双倍容量<强> 18个数量级。比较一下,将 1999!存储在一个双倍中就像试图在典型的0.1μm直径的细菌中拟合从太阳中心到地球中心的距离。