Search code examples
c++rounding-error

Defining a range despite C++ rounding errors


Given a lower bound, upper bound, and step, I would like to create a vector that lists containing numbers that start at the lower bound, and step up to the higher bound, separated by the step. e.g. lower = 1.5, upper = 6.0, step = 1.0: return [1.5, 2.5, 3.5, 4.5, 5.5].

My code in C++ is currently:

#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;
}

It ideally should work fine, but rounding errors keep making it output the wrong things. For example,

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

will sometimes output 99 and not 100, presumably because 10^-7 is being represented as 9.9999...9*10^-8.

I was wondering, is there some kind of method or trick that can help me avoid these problems?


Solution

  • For what it's worth, this would be more straight forward to do with a std::vector and a for loop.

    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

    This will keep the actual values as close as possible to the correct floating point value without accumulating rounding errors. You can still output the values to your preferred precision using the <iomanip> library.