满足两个条件时,如何在C ++中停止For循环?

时间:2018-10-25 18:18:04

标签: c++ math trigonometry sine taylor-series

我试图让我的for循环在满足两个条件时停止运行。 n计数器没有给我一个问题。我基本上希望循环在循环开始后一旦totalSum等于其自身(或在其一定余量内)就停止运行。 我是编码的初学者,是本网站的新手,所以我提前致歉。为了代表任何人进行测试,我将完整地包含代码。

我将在此处提供更多信息。我的代码运行正常,尽管在循环过程中,正在计算的值变得很大,并且出现了naninf的字样。在打印出totalSum等之后。我看到我得到了一次或两次重复的值(正确的正弦计算),但此后,该数字一直由循环递增或递减。在100次循环之后,我的循环最终结束后,我得到了上面提到的nan / inf

long double sine(double x)                                       
{
long double totalSum = 0.0;

for(int n = 0; n < 100; ++n)
{
    int plusOrMinusSign = pow(-1, n);
    long double num = pow(x,(2 * n + 1));
    long double den = factorialtest(2 * n + 1);
    totalSum += (plusOrMinusSign * num / den);
    cout <<plusOrMinusSign<<" "<< x << "^" <<(2*n+1) <<"/"<< (2 * n + 1)<<"! = " << totalSum <<endl; //testing purposes
}
return totalSum;
}

下面的整个程序

#include <iostream>
#include <cmath>    //used for pow indicated in comment with "^"
#include <iomanip>
using namespace std;

long int factorialtest(int x) //calculates factorial
{
long int factorialNum = 1;
for(int count = 1; count <= x; count++)
    factorialNum = factorialNum * count;
return factorialNum;
}

long double sine(double x)                                             
{
long double totalSum = 0.0;

for(int n = 0; n < 100; ++n)
{
    int plusOrMinusSign = pow(-1, n);
    long double num = pow(x,(2 * n + 1));
    long double den = factorialtest(2 * n + 1);
    totalSum += (plusOrMinusSign * num / den);
    cout <<plusOrMinusSign<<" "<< x << "^" <<(2*n+1) <<"/"<< (2 * n + 1)<<"! = " << totalSum <<endl; //testing purposes
}
return totalSum;
}

double cosine(double x)                     //returns cos of x
{
double totalSum = 0;

for(int n = 0; n < 100; n = n + 2)
{
    double num = pow(x,(n));            // ^ used pow here, does the power of x to the n value above
    double den = factorialtest(n);      //used my own factorial program here, multiplies n by factorial of n
    totalSum = totalSum + ( num / den);
}
return totalSum = 0;
}

double tangent(double x) {      //returns tangent
return sine(x) / cosine(x);
}

double secant(double x) {       //returns secant
return 1 / cosine(x);
}

double cosecant(double x) {     //returns cosecant
return 1 / sine(x);
}

double  cotangent(double x) {   //returns cotangent
return 1 / tangent(x);
}

int main() {

double x;

cout << "Input number to find sine: ";
cin >> x;
cout << "Sine of " << x << " is " << sine(x) << endl;


}

程序计算弧度btw。下面使用x表示1的情况。 “ Sine(1)”

-1 1^63/63! = 0.841471
1 1^65/65! = 0.841471
-1 1^67/67! = -inf

在某一点之后,它给了我。谢谢您的宝贵时间。

5 个答案:

答案 0 :(得分:1)

您对阶乘函数的使用有缺陷-输入21时,它的溢出将非常小!将溢出64位带符号整数类型。

您正在观察的是未定义的行为,该行为表现为以2的大方模为模,以零为模,因为即使很小的阶乘也将是2的方的倍数。

在IEEE754之下,被零除的结果为Inf(如果分子为负,则为-Inf)。

您可以通过简单地将前一个系数乘以一个迭代步骤函数的值来修正算法,但是请注意,内置三角函数不会使用此方法进行评估,因此此练习纯粹是学术性的。

您的实际问题:您可以将多个条件作为停止条件:&&和||的使用很常见。

答案 1 :(得分:0)

如果不仔细查看您的代码,您可能会遇到类似这样的情况:

int j = 0;
for(int i = 0; i < 10 && j < 10; i++, j += 2)
{
    std::cout << "i: " << i << " j: " << j << endl;
}

答案 2 :(得分:0)

通常来说,有两种方法可以中断任何条件循环。

1-您满足一些不再有效的循环条件:

while( myConditionIsTrue() ) 
{
    ...
}

其中myConditionIsTrue()是可以评估为非0或布尔值的任何值。对于无限循环,它可以像true一样简单,对于简单条件,它可以像x == y一样复杂,或者像x == y && a != b一样复杂,甚至可以返回将继续执行的方法调用或打破循环。

我向您展示了一个while循环,但是一个for循环却是相同的,其中for实际上是:

for(initializationCode(); myConditionIsTrue(); thisCodeRunsAtTheEndOfEachIteration()) 
{
    ...
}

2-您明确地跳出了循环:

使用关键字break可以让您在任何给定时间中断任何循环,如果遇到意外情况,请使用它,因此它不会成为循环主要条件的一部分,但是要小心在您使用它时,由于多个退出点会使代码难以理解和阅读。

while(x != y) 
{
    if(x < 0) 
    {
        break; // interrupts the while loop.
    }
}

还有工作的continue,它不会中断循环,只是忽略了此迭代中的其余循环,而跳到了下一个迭代,转而请求循环。

答案 3 :(得分:0)

factorial已经为小n溢出了。您应该使用更长的类型,但不能解决真正的问题。考虑到您在每次迭代中添加的增量实际上是一个很小的数字,并且您可以轻松地从上一步中的增量中计算出增量:

double increment = 1;
for(int n = 0; n < 100; ++n) {
    int plusOrMinusSign = n % 2;
    totalSum += (plusOrMinusSign * increment);
    increment *= x;                        // exponential part
    increment /= (n+1);                    // factorial part 
}

我没有费心把数学正确,但是我希望你能理解。 x是固定的,并且n仅线性增长,因此几乎没有溢出的危险(尤其是您期望increment0收敛)。

我没有得到您想要用作第二条件的东西。但是,为了完整起见:假设条件为A和B,则可以通过以下方式中断循环:

for (int i; A && B; ++i) { }

for (int i; ; ++i) {
     if (A && B) break;
}

至少有第三种方式,但是为了避免引起讨论,我将其留给有兴趣的读者来查找:P。

答案 4 :(得分:0)

如果我被误解了,请纠正我,但是听起来好像您想在totalSum的新值接近旧值的情况下跳出循环。这意味着您必须能够查看新值和旧值之间的差异。在这种情况下,这很容易:两者之间的区别仅仅是plusOrMinusSign * num / den。因此,将其存储为命名变量并在循环顶部对其进行测试:

long double adjust = 10000; // large enough that it won't quit on entry
for (int n = 0; n < 100 && my_epsilon < std::abs(adjust); ++n) {
    int plusOrMinusSign = pow(-1, n);
    long double num = pow(x,(2 * n + 1));
    long double den = factorialtest(2 * n + 1);
    adjust = plusOrMinusSign * num / den;
    totalSum += adjust;
    cout <<plusOrMinusSign<<" "<< x << "^" <<(2*n+1) <<"/"<< (2 * n + 1)<<"! = " << totalSum <<endl; //testing purposes
}

您必须确定my_epsilon的值;确定退出循环所需的差异有多小。

当我在这里时,int plusOrMinusSign = pow(-1, n)不是切换标志的好方法;求幂会很慢。而是在循环之前初始化该值:

int plusOrMinusSign = 1;

,然后在循环主体的末尾,只需对其进行切换即可:

plusOrMinusSign *= -1;

或将该更改放入循环增量中:

for (int n = 0; n < 100 && my_epsilon < std::abs(adjust); ++n, plusOrMinusSign *= -1)

最后一个可能对某些人来说令人反感。