【问题标题】:My for-loop does not start [duplicate]我的for循环没有启动[重复]
【发布时间】:2014-07-18 02:26:50
【问题描述】:

我知道有很多关于这个问题的话题,但没有一个对我有帮助。我试图通过测试 -10 到 10 范围内的每个数字(带两位小数)来找到函数的根。我知道这可能不是最好的方法,但我是初学者,只想尝试一下。不知何故,循环不起作用,因为我总是得到 -10 作为输出。 无论如何,这是我的代码:

 #include <iostream>
using namespace std;

double calc (double m,double n)
{
  double x;
  for (x=-10;x<10 && m*x+n==0; x+=0.01)
  {
   cout << x << endl;
  }
  return x;
}



int main()
{
  double m, n, x;

  cout << "......\n";
  cin >> m;                         // gradient
  cout << "........\n";
  cin >> n;                         // y-intercept
  x=calc(m,n);                      // using function to calculate
  cout << ".......... " << x<< endl; //output solution
  cout << "..............\n";        // Nothing of importance
  return 0;
}

【问题讨论】:

  • 尽量避免使用双精度/浮点数,并尽可能使用整数。所以像for (x=-1000;x&lt;1000 &amp;&amp; m*(x/100)+n==0; x+=1)。然后在打印结果时可以将 x 的值除以 100。
  • 我更新了我的答案,提供了一种解决方法。
  • 您完全确定 m*x+n==0 实际做了什么,是吗?
  • 但我认为整数只支持完整的数字,但我希望它更精确。哦,我已将 mx+n==0 更改为 mx+n!=0 现在它输出 10,所以没有任何改进
  • @ubuntu.stuff 您需要检查std::numeric_limit::epsilon0.0 的区别才能做到这一点!见这里Compare double to zero using epsilon

标签: c++ for-loop


【解决方案1】:

您正在测试循环条件中两个条件的结合。

for (x=-10;x<10 && m*x+n==0; x+=0.01

对于许多输入,第二个条件不成立,因此循环将在第一次迭代之前终止,导致返回值-10

您想要的可能更接近于以下内容。我们需要测试绝对值是否小于某些EPSILON,原因有两个。一、double 不准确。第二,反正你是在做一个近似的解决方案,所以除非你碰巧运气好,否则你不会期望得到一个准确的答案。

#define EPSILON 1E-2
double calc (double m,double n)
{
    double x;
    for (x=-10;x<10; x+=0.001)
    {
        if (abs(m*x+n) < EPSILON) return x;
    }

    // return a value outside the range to indicate that we failed to find a
    // solution within range.
    return -20;
}

更新:应OP的要求,我将更具体地说明EPSILON解决了什么问题。

  1. double 不准确。在计算机中,浮点数通常由固定数量的位表示,位表示通常由标准指定,例如IEE 754。因为位数是固定的且有限的,所以您不能表示任意精度的数字。为了便于理解,让我们考虑一个以 10 为基数的示例,尽管您应该了解计算机在以 2 为基数时会遇到类似的问题。 如果m = 1/3x = 3n = -1,我们期望m*x + n == 0。但是,因为1/3是重复的十进制0.33333...,而我们只能表示它们的固定数量,所以3*0.33333的结果实际上是0.999999,不等于1。因此,m*x + n != 0,我们的检查将失败。因此,我们必须通过将其绝对值与我们称为EPSILON 的小数进行比较,而不是检查是否与零相等,而是检查结果是否足够接近零。正如其中一位 cmet 指出的那样,EPSILON 的正确值是std::numeric_limits::epsilon,但第二个问题需要更大的EPSILON

  2. 无论如何,您只是在做一个近似的解决方案。由于您正在以有限的小增量检查x 的值,因此您很可能会简单地越过根,而不会准确地落在它上面。考虑方程10000x + 1 = 0。正确的解决方案是-0.0001,但如果您采取0.001 的步骤,您将永远不会真正尝试x = -0.0001 的值,因此您不可能找到正确的解决方案。对于线性函数,我们希望x 的值接近于-0.0001,例如x = 0,将使我们合理地接近正确的解决方案,因此我们使用EPSILON 作为一个捏造因素来解决缺乏的问题我们方法的精度。

【讨论】:

  • 什么是 EPSILON?你能否再解释一下你的代码,我就是不明白。:)
  • epsilon 这里是一个容差……在处理浮点数时,您应该非常怀疑 '==' 运算符。除非双精度的小数部分为零或 2 的某个幂(例如 0.5 或 .25 或 0.125 等...),否则它将是最接近的舍入 近似值 base_2 中可能的实际 base_10 数。因此,对“等于零”的最可靠检查是检查某个值是否小于我们实际上可以视为零的值。
  • 好吧,我想我会等待那个程序。我不太了解,但无论如何还是非常感谢:D顺便说一句。这里有很多巫师,不是吗? Merlin2011,Hexedagain……难怪我做不到……
  • @πάνταῥεῖ 我很难看到机器 epsilon 对这个问题的实用性。例如,如果 m > 1, n > 0 那么由于 log_10(mx) > 1 那么 mx + n 和下一个可表示的 double 之间的距离将明显大于机器 epsilon。相反,如果 m 非常小,那么相对于 m*x 和下一个可表示对象之间的距离,机器 epsilon 可能会很大!
  • @merlin2011,std::numeric_limits::epsilon 不正确缩放是不正确的,这取决于 m 的大小
【解决方案2】:

m*x+n==0 条件返回false,因此循环不会开始。 你应该把它改成m*x+n!=0

【讨论】:

  • '你应该把它改成m*x+n!=0'这不会严重破坏语义吗?
  • 我做了,但现在它总是输出 10 所以它仍然不起作用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-31
  • 2018-02-14
  • 2012-06-02
  • 2015-06-12
相关资源
最近更新 更多