【问题标题】:Defining a range despite C++ rounding errors尽管存在 C++ 舍入错误,但仍定义范围
【发布时间】:2015-05-13 05:26:48
【问题描述】:

给定一个下限、上限和步长,我想创建一个向量,其中列出了包含从下限开始的数字,然后逐步上升到上限,由步长分隔。 例如下 = 1.5,上 = 6.0,步长 = 1.0: 返回 [1.5, 2.5, 3.5, 4.5, 5.5]。

我的 C++ 代码目前是:

#include<iostream>
#include<armadillo>
using namespace std;
using namespace arma;

vec createArray( double lower, double upper, double step) {

    int arrayLength = int ((upper - lower)/step + 1);
    vec array(arrayLength);
    for( int j = 0; j < arrayLength; j += 1 )
    {
        array(j) = lower + j*step;
    }
    return array;
}

理想情况下它应该可以正常工作,但舍入错误不断使其输出错误的东西。例如,

int((pow(10,-7)-0)/pow(10,-9));

有时会输出 99 而不是 100,大概是因为 10^-7 被表示为 9.9999...9*10^-8。

我想知道,有没有什么方法或技巧可以帮助我避免这些问题?

【问题讨论】:

标签: c++ rounding-error


【解决方案1】:

使用矢量,您无需事先了解容器的大小。因此,只需创建一个在您超过最大值时停止的循环。这是一些伪代码。

vector<double> createVector(double minVal, double maxVal, double step)
{
    vector<double> data;

    while(minVal < maxVal){  
       data.push_back(minVal);   
       minVal += step;
    }

      return data;
}

【讨论】:

    【解决方案2】:

    对于它的价值,使用std::vectorfor 循环会更直接。

    std::vector<double> createArray(double lower, double upper, double step)
    {
        std::vector<double> values;
        for (double value = lower; value <= upper; value += step)
        {
            values.push_back(value);
        }
        return values;
    }
    

    Working example

    这将使 实际值 尽可能接近正确的浮点值,而不会累积舍入误差。您仍然可以使用 &lt;iomanip&gt; 库将值输出到您喜欢的精度。

    【讨论】:

    • 或者使用 C++11 基于范围的 for,也许结合 lambdas。
    • @ErikAlapää 当然,有更巧妙的方法可以做到这一点,我只是想把这个想法传达出去。可能std::iotastd::back_inserter 的组合可以解决问题。
    • @ErikAlapää 都不适合此代码示例。
    • @remyabel。我不同意。请详细说明为什么两者都不合适?
    • @ErikAlapää 基于范围的 for 循环通常用于迭代具有填充元素的容器,因为它只是使用容器 begin()end() 以避免不得不为循环创建一个迭代器变量。如果要填充容器,则基于范围的 for 循环将无法迭代。类似地,lambda 通常用于代替函子。我不确定您对使用 lambda 有什么想法,我敢肯定会有一些用例。
    【解决方案3】:

    您应该std::round 结果而不是截断。只要您的整数在您的浮点类型中完全可以表示,这至少可以工作。

    【讨论】:

      猜你喜欢
      • 2014-01-08
      • 1970-01-01
      • 2017-04-17
      • 1970-01-01
      • 2021-11-28
      • 2015-10-12
      • 2015-12-26
      • 2022-12-31
      • 2021-08-06
      相关资源
      最近更新 更多