I am looking to get :
input:
arange(0.0,0.6,0.2)
output:
0.,0.4
I want
0.,0.2,0.4,0.6
how do i achieve using range or arange. If not what is alternate ?
I am looking to get :
input:
arange(0.0,0.6,0.2)
output:
0.,0.4
I want
0.,0.2,0.4,0.6
how do i achieve using range or arange. If not what is alternate ?
 
    
     
    
    A simpler approach to get the desired output is to add the step size in the upper limit. For instance,
np.arange(start, end + step, step)
would allow you to include the end point as well. In your case:
np.arange(0.0, 0.6 + 0.2, 0.2)
would result in
array([0. , 0.2, 0.4, 0.6]).
 
    
    Had a bug in the code for stop - start being a non-integer number of steps => fixed
unexpected behavior:
>>> np.arange(1, 1.3, .1)  # UNEXPECTED
array([1. , 1.1, 1.2, 1.3])
fix:
>>> from arange_cust import *
>>> np_arange_closed(1, 1.3, .1)
array([1. , 1.1, 1.2, 1.3])
>>> np_arange_open(1, 1.3, .1)
array([1. , 1.1, 1.2])
I had your problem a few times as well. I usually quick-fixed it with adding a small value to stop. As mentioned by Kasrâmvd in the comments, the issue is a bit more complex, as floating point rounding errors can occur in numpy.arange (see here and here).
Unexpected behavior can be found in this example:
>>> np.arange(1, 1.3, 0.1)
array([1. , 1.1, 1.2, 1.3])
To clear up things a bit for myself, I decided to be very careful with np.arange.
arange_cust.py:
import numpy as np
def np_arange_cust(
        *args, rtol: float=1e-05, atol: float=1e-08, include_start: bool=True, include_stop: bool = False, **kwargs
):
    """
    Combines numpy.arange and numpy.isclose to mimic open, half-open and closed intervals.
    Avoids also floating point rounding errors as with
    >>> np.arange(1, 1.3, 0.1)
    array([1., 1.1, 1.2, 1.3])
    Parameters
    ----------
    *args : float
        passed to np.arange
    rtol : float
        if last element of array is within this relative tolerance to stop and include[0]==False, it is skipped
    atol : float
        if last element of array is within this relative tolerance to stop and include[1]==False, it is skipped
    include_start: bool
        if first element is included in the returned array
    include_stop: bool
        if last elements are included in the returned array if stop equals last element
    kwargs :
        passed to np.arange
    Returns
    -------
    np.ndarray :
        as np.arange but eventually with first and last element stripped/added
    """
    # process arguments
    if len(args) == 1:
        start = 0
        stop = args[0]
        step = 1
    elif len(args) == 2:
        start, stop = args
        step = 1
    else:
        assert len(args) == 3
        start, stop, step = tuple(args)
    arr = np.arange(start, stop, step, **kwargs)
    if not include_start:
        arr = np.delete(arr, 0)
    if include_stop:
        if np.isclose(arr[-1] + step, stop, rtol=rtol, atol=atol):
            arr = np.c_[arr, arr[-1] + step]
    else:
        if np.isclose(arr[-1], stop, rtol=rtol, atol=atol):
            arr = np.delete(arr, -1)
    return arr
def np_arange_closed(*args, **kwargs):
    return np_arange_cust(*args, **kwargs, include_start=True, include_stop=True)
def np_arange_open(*args, **kwargs):
    return np_arange_cust(*args, **kwargs, include_start=True, include_stop=False)
To avoid bugs in future, here is a testing module. In case we find something again, lets add a testcase. test_arange_cust.py:
import numpy as np
from arange_cust import np_arange_cust, np_arange_closed, np_arange_open
import pytest
class Test_np_arange_cust:
    paras_minimal_working_example = {
        "arange simple": {
            "start": 0, "stop": 7, "step": 1, "include_start": True, "include_stop": False,
            "res_exp": np.array([0, 1, 2, 3, 4, 5, 6])
        },
        "stop not on grid": {
            "start": 0, "stop": 6.5, "step": 1, "include_start": True, "include_stop": False,
            "res_exp": np.array([0, 1, 2, 3, 4, 5, 6])
        },
        "arange failing example: stop excl": {
            "start": 1, "stop": 1.3, "step": .1, "include_start": True, "include_stop": False,
            "res_exp": np.array([1., 1.1, 1.2])
        },
        "arange failing example: stop incl": {
            "start": 1, "stop": 1.3, "step": .1, "include_start": True, "include_stop": True,
            "res_exp": np.array([1., 1.1, 1.2, 1.3])
        },
        "arange failing example: stop excl + start excl": {
            "start": 1, "stop": 1.3, "step": .1, "include_start": False, "include_stop": False,
            "res_exp": np.array([1.1, 1.2])
        },
        "arange failing example: stop incl + start excl": {
            "start": 1, "stop": 1.3, "step": .1, "include_start": False, "include_stop": True,
            "res_exp": np.array([1.1, 1.2, 1.3])
        },
    }
    @pytest.mark.parametrize(
        argnames=next(iter(paras_minimal_working_example.values())).keys(),
        argvalues=[tuple(paras.values()) for paras in paras_minimal_working_example.values()],
        ids=paras_minimal_working_example.keys(),
    )
    def test_minimal_working_example(self, start, stop, step, include_start, include_stop, res_exp):
        res = np_arange_cust(start, stop, step, include_start=include_start, include_stop=include_stop)
        assert np.allclose(res, res_exp), f"Unexpected result: {res=}, {res_exp=}"
 
    
    Interesting that you get that output. Running arange(0.0,0.6,0.2) I get:
array([0. , 0.2, 0.4])
Regardless, from the numpy.arange docs: Values are generated within the half-open interval [start, stop) (in other words, the interval including start but excluding stop). 
Also from the docs: When using a non-integer step, such as 0.1, the results will often not be consistent. It is better to use numpy.linspace for these cases
The only thing I can suggest to achieve what you want is to modify the stop parameter and add a very small amount, for example
np.arange(0.0, 0.6 + 0.001 ,0.2)
Returns
array([0. , 0.2, 0.4, 0.6])
Which is your desired output.
Anyway, it is better to use numpy.linspace and set endpoint=True
 
    
    Old question, but it can be done much easier.
def arange(start, stop, step=1, endpoint=True):
    arr = np.arange(start, stop, step)
    if endpoint and arr[-1]+step==stop:
        arr = np.concatenate([arr,[end]])
    return arr
print(arange(0, 4, 0.5, endpoint=True))
print(arange(0, 4, 0.5, endpoint=False))
which gives
[0.  0.5 1.  1.5 2.  2.5 3.  3.5 4. ]
[0.  0.5 1.  1.5 2.  2.5 3.  3.5]
 
    
    A simple example using np.linspace (mentioned numerous times in other answers, but no simple examples were present):
import numpy as np
start = 0.0
stop = 0.6
step = 0.2
num = round((stop - start) / step) + 1   # i.e. length of resulting array
np.linspace(start, stop, num)
>>> array([0.0, 0.2, 0.4, 0.6])
Assumption: stop is a multiple of step. round is necessary to correct for floating point error.
 
    
    Ok I will leave this solution, here. First step is to calculate the fractional portion of number of items given the bounds [a,b] and the step amount. Next calculate an appropriate amount to add to the end that will not effect the size of the result numpy array and then call the np.arrange().
import numpy as np
def np_arange_fix(a, b, step):
    nf = (lambda n: n-int(n))((b - a)/step+1)
    bb = (lambda x: step*max(0.1, x) if x < 0.5 else 0)(nf)
    arr = np.arange(a, b+bb, step)
    if int((b-a)/step+1) != len(arr):
        print('I failed, expected {} items, got {} items, arr-out{}'.format(int((b-a)/step), len(arr), arr))
        raise
    return arr
print(np_arange_fix(1.0, 4.4999999999999999, 1.0))
print(np_arange_fix(1.0, 4 + 1/3, 1/3))
print(np_arange_fix(1.0, 4 + 1/3, 1/3 + 0.1))
print(np_arange_fix(1.0, 6.0, 1.0))
print(np_arange_fix(0.1, 6.1, 1.0))
Prints:
[1. 2. 3. 4.]
[1.         1.33333333 1.66666667 2.         2.33333333 2.66666667
 3.         3.33333333 3.66666667 4.         4.33333333]
[1.         1.43333333 1.86666667 2.3        2.73333333 3.16666667
 3.6        4.03333333]
[1. 2. 3. 4. 5. 6.]
[0.1 1.1 2.1 3.1 4.1 5.1 6.1]
If you want to compact this down to a function:
def np_arange_fix(a, b, step):
    b += (lambda x: step*max(0.1, x) if x < 0.5 else 0)((lambda n: n-int(n))((b - a)/step+1))
    return np.arange(a, b, step)
 
    
    When it's easier to type the end value than the step, I do:
np.arange(0, 100e3+1)/100e3
