3

I am trying to create a range of floats, however, it seems adding one step to the range results in two added steps, any ideas on how to solve this without creating a list of integers and then dividing by 10 (I avoid that as the step could be 0.3 as well)

import numpy as np

amp_start = 0.8
amp_step = 0.1
amp_end = 1.0
amp_end = (np.ceil(amp_end / amp_step)) * amp_step
amp_end_2 = (np.ceil(amp_end / amp_step)) * amp_step + amp_step

print(amp_end)
field_amp_range = np.arange(amp_start, amp_end, amp_step)
field_amp_range_2 = np.arange(amp_start, amp_end_2, amp_step)
field_amp_range = field_amp_range.tolist()
print(amp_end, amp_end_2, field_amp_range, field_amp_range_2)

EDIT: amp_start = 0.8 (or = 0.0) was missing

1 Answer 1

2

Although I can't reproduce it on my computer, this sounds like a floating-point rounding error problem. The np.arange documentation:

When using a non-integer step, such as 0.1, the results will often not be consistent. It is better to use linspace for these cases.

So using linspace is probably best. Here is an example using linspace:

import numpy as np

amp_start = 0.8
amp_step = 0.1
amp_end = 1.0
amp_end = (np.ceil(amp_end / amp_step)) * amp_step
amp_end_2 = (np.ceil(amp_end / amp_step)) * amp_step + amp_step

print(amp_end)
field_amp_range = np.linspace(amp_start, amp_end, np.rint((amp_end-amp_start)/amp_step).astype('int')+1)
field_amp_range_2 = np.linspace(amp_start, amp_end_2, np.rint((amp_end_2-amp_start)/amp_step).astype('int')+1)
field_amp_range = field_amp_range.tolist()
print(amp_end, amp_end_2, field_amp_range, field_amp_range_2)

Alternatively, if you really want to keep using np.arange, and you're sure that there is an integer number of steps between the start and end values, you could add a small number to the end value, so that the rounding off does not matter (or subtract it, if you do not want the end value to be encluded in your list). In that case your code would become:

import numpy as np
amp_start = 0.
amp_step = 0.1
amp_end = 1.0
amp_end = (np.ceil(amp_end / amp_step)) * amp_step
amp_end_2 = (np.ceil(amp_end / amp_step)) * amp_step + amp_step

print(amp_end)
field_amp_range = np.arange(amp_start, amp_end+amp_step/100, amp_step)
field_amp_range_2 = np.arange(amp_start, amp_end_2+amp_step/100, amp_step)
print(amp_end, amp_end_2, field_amp_range, field_amp_range_2)
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks @Ewoud, even with linspace I get a similar behavior: amp_count = np.ceil((amp_end - amp_start)/amp_step)+1 field_amp_range = np.arange(amp_start, amp_end, amp_step)
Can you try to use np.rint instead of np.ceil? np.ceil will be very sensitive to numerical round-off errors when the result is close to an integer.
import numpy as np amp_start = 0.6 amp_start_2 = 0.8 amp_step = 0.1 amp_end = 0.9 amp_end = (np.rint(amp_end / amp_step)) * amp_step field_amp_range = np.arange(amp_start, amp_end, amp_step) field_amp_range_2 = np.arange(amp_start_2, amp_end, amp_step) print(field_amp_range, field_amp_range_2) even with rint i get the same; something else which is strange is the dependence of the results on the start value
I forgot to mention, the initial reason I used np.ceil instead of np.rint was to cover the cases where the amp_end is not a multiple of amp_step, e.g. amp_end = 1.01 and amp_step = 0.1
I added an example with linspace. But it is not entirely clear what you want if there is not an integer number of steps between amp_start and amp_end. Should it just behave like np.arange?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.