for循环问题(初学者)

时间:2014-07-23 14:15:47

标签: c++ vector

我开始学习c ++,我得到了这个简单的程序: (我提前为我的英语道歉)

#include <iostream>
#include <vector>
#include <string>

using namespace std;

vector<double> time_vector(int interval[], float increment)
{
    vector<double> time; 
    for (double i=interval[0]; i<=interval[1]; i=i+increment)
        time.push_back(i);
    return time;
}

int main(int argc, char** argv) {

    int interval[] = {0,3};
    float increment = 0.1;
    vector<double> time = time_vector(interval, increment);

    for (vector<double>::iterator it=time.begin(); it!=time.end(); ++it)
        cout << *it << " ";
    return 0;
}

time_vector函数的想法是创建一个范围为[a,b]的向量,并以增量值递增自身。这将模仿来自matlab的命令

a:increment:b

但是当我运行它时,我明白了:

0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2 2.1 2.2        2.3 2.4 2.5 2.6 2.7 2.8 2.9 0 

正如您所看到的那样,最后一个元素不是3.0。我做得对吗?

4 个答案:

答案 0 :(得分:4)

很可能是浮点精度问题。参见floating point guide(每个程序员应该知道的浮点运算)

0.1中{{1}}

PS。它本身不是C ++问题。您将在C,Ada或Fortran中遇到相同的问题。

答案 1 :(得分:3)

问题与internal floating point representations有关:在for循环的最后一个循环中,这可能发生了什么

i = 2.9000000432133675
increment = 0.100000001

i + increment = 3.0000000442133675 

因此不再符合条件,您将不会存储最后预期的结果。

您可能希望在结果中添加epsilon值以确保正确性,例如

#include <iostream>
#include <vector>
#include <string>

using namespace std;

#define EPSILON 0.0000001

vector<double> time_vector(int interval[], float increment)
{
    vector<double> time; 
    for (double i=interval[0]; i<=interval[1] + EPSILON; i=i+increment)
        time.push_back(i);
    return time;
}

int main(int argc, char** argv) {

    int interval[] = {0,3};
    float increment = 0.1f;
    vector<double> time = time_vector(interval, increment);

    for (vector<double>::iterator it=time.begin(); it!=time.end(); ++it)
        cout << *it << " ";
    return 0;
}

http://ideone.com/WRi2ln

的Nb。这并不意味着C ++ 不如Matlab 精确。 Matlab内部处理所有这些技巧和权衡,但只是让它对你不透明,让你专注于其他事情(C ++允许你做更多低级别的东西,但这是你为它付出的代价)。

答案 2 :(得分:1)

由于浮点表示和循环结构的方式,无法保证向量中存在范围中的最后一个数字。避免这种情况的一种方法是计算所需的步数以生成所需的范围并执行计算,如下所示:

std::vector<double> time_vector(int interval[], float increment)
{
    std::vector<double> time; 
    int nSteps = (int)((interval[1] - interval[0]) / increment + 0.5f); //Rounding

    time.push_back(interval[0]);
    for (int i = 1; i <= nSteps; ++i)
    {
        time.push_back(interval[0] + i * increment);
    }
    return time;
}

答案 3 :(得分:0)

我注意到你在double,float和int之间做了很多隐式转换。不要将间隔存储为两个整数,而是尝试将其存储为浮点数,您还可以通过浮点数递增时间向量中的值,尽管它们存储为双精度数。尝试使用统一类型,因此列表隐式转换:

vector<float> time_vector(float interval[], float increment)
{
    vector<float> time; 
    for (float i=interval[0]; i<=interval[1]; i=i+increment)
        time.push_back(i);
    return time;
}

int main(int argc, char** argv) {

    float interval[] = {0,3};
    float increment = 0.1;
    vector<float> time = time_vector(interval, increment);

    for (vector<float>::iterator it=time.begin(); it!=time.end(); ++it)
        cout << *it << " ";
    return 0;
}