2

I have the radius of a circle and the equation y = int(math.sqrt(pow(radius, 2)-pow(i,2))) (Pythagoras).
Now I want to loop over the range range(-radius,0) + range(1, radius+1) within a multiple of 16 steps like this:

radius = 4
Actually output: -4, -3, -2, 1, 1, 2, 3, 4
What I want: -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4

And I found out, that you can't change the step-size of for-loops easily but I found a way:

print("Length: ", len([x/2 for x in chain(range(-2*radius, 0), range(1,2*radius+1))]))
print("Values: ", [x/2 for x in chain(range(-2*radius, 0), range(1,2*radius+1))])

Which returns 16 and the wanted "count", as I mentioned above.

Now my question is: How can I automate this? Because that it works with 4 is just a "coincidence" and with e.g. radius = 5 it won't work like this. So is there a solution that I can loop through a range in x steps?

Niklas
  • 109
  • 1
  • 10
  • Possible duplicate of [Python decimal range() step value](http://stackoverflow.com/questions/477486/python-decimal-range-step-value) – Prune Feb 08 '17 at 22:35
  • You can use Numpy, and there is a function that creates lists like what you're trying to do. `numpy.linspace(-radius, radius, radius * radius)` – kbunarjo Feb 08 '17 at 22:35
  • The equation of a circle should be `sqrt(radius * radius - x * x)` (square-root instead of `int`), assuming iteration variable is `x`. This will give the upper part of the circle. – Sci Prog Feb 08 '17 at 22:40
  • ... the numpy solution is included in the duplicate question. – Prune Feb 08 '17 at 22:40
  • @SciProg yeah, thanks – Niklas Feb 08 '17 at 22:48

4 Answers4

1

Solution 1.1:

You can use the linspace-function and then pick those values which are not 0. This is done by the my_range-function in the following code:

import numpy as np

def my_range(radius, steps):
    ran = np.linspace(-radius, radius, steps+1)
    return ran[np.nonzero(ran)]

Now,

[i for i in my_range(4, 16)]

produces

[-4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]

Solution 1.2:

Alternatively,

list(my_range(4, 16))

produces the same list.


Solution 2:

If you don't want to define a function, here is a concise way to achieve the same thing:

[i for i in np.linspace(-4, 4, 16+1) if i != 0]
yogabonito
  • 627
  • 4
  • 12
  • Thanks! This one worked but please note, that the solution from another use (sadly he deleted his post again...) is a bit faster: `range_steps = (num * 2) / float(steps) #calculate the increment value to get you your step count (LINEBREAK) return list(np.arange(num * -1, num , range_steps))` – Niklas Feb 08 '17 at 23:12
  • @Niklas the code in your comment produces a list which contains the 0 in the middle of it. And it does not include the last value of the list in my example. So the code in your comment produces something different than what you defined as the desired result. – yogabonito Feb 08 '17 at 23:22
  • yeah, I saw that in the same moment... I mean the problem with the 0 is easy to fix, because you can delete it afterwards and the algorithm would still be faster, but the problem with the last value isn't that easy to fix I think – Niklas Feb 08 '17 at 23:29
  • You are right about the 0. But I really recommend to use `linspace` instead of `arange` when dealing with steps of type float. Try out `np.arange(0, 1.1, 0.1)` and `np.arange(0.5, 1.1, 0.1)`, compare their last values and ... surprise! They are different! (This example is adapted from [this page](http://quantumwise.com/forum/index.php?topic=110.0).) – yogabonito Feb 08 '17 at 23:57
  • Yeah, you're right! But take a look at @f5r5e5d's solution! This one needs nothing and works the same I think, doesn't it? (if you round the result its nearly the same) – Niklas Feb 09 '17 at 00:02
  • Well, both contain 0. In his first solution you have to consider to use `n=17` instead of `n=16`. And his second solution didn't produce the last value in the list when I tried it out. So with a little tweaking you could also use @f5r5e5d's version. I would choose the one I find more readable :) – yogabonito Feb 09 '17 at 00:14
  • for me @f5r5e5d's solution produces the last value and don't contain 0 but I think, that I choose ur solution! :D – Niklas Feb 09 '17 at 12:18
0

Hope you like this solution, __future__ import is for python 2.x:

from __future__ import division
r = 4
result = [-a/2 for a in xrange(1, r*2+1)][::-1] + [a/2 for a in xrange(1, r*2+1)]
print result
zipa
  • 26,044
  • 6
  • 38
  • 55
  • Thanks! This solution works, but please keep in mind, that this is really slow in comparision to @yogabonito's method! :) – Niklas Feb 08 '17 at 23:08
  • 2
    By really slow I mean: For 9999 calculations yours need 17 secs and yogabonito's need 0,05 :D – Niklas Feb 08 '17 at 23:09
0

it looks like you want +/- limits equal magnitude

you then have the choice of include the endpoint in the range, and if that then makes you want to get n + 1 points

pure python, no imports:

lim, n = 3, 10

[-lim + i * 2 * lim / (n - 1) for i in range(n)]
Out[27]: 
[-3.0,
 -2.3333333333333335,
 -1.6666666666666667,
 -1.0,
 -0.3333333333333335,
 0.3333333333333335,
 1.0,
 1.666666666666667,
 2.333333333333333,
 3.0]

or

[-lim + i * 2 * lim / n for i in range( n + 1)]
Out[28]: 
[-3.0,
 -2.4,
 -1.8,
 -1.2,
 -0.6000000000000001,
 0.0,
 0.6000000000000001,
 1.2000000000000002,
 1.7999999999999998,
 2.4000000000000004,
 3.0]

changing the list comprehension sq brackets to round makes a generator that could be used in place of range()

f5r5e5d
  • 3,456
  • 3
  • 13
  • 18
-1

range function takes three parameters start , stop and step (third argument is optional) . range(-4,4,0.5) will solve your problem. so let's assume -x is start and x is stop.

step =  int(x/16);
range(-x, x, step);
Nirmal Dey
  • 183
  • 5