Why is my program stopping when doing a seemingly infinite loop? - python

This must be really obvious but I am currently doing a little tutorial that features this code snippet:
n=0
a=1
while a>0:
n=n+1
a=(1.0+2.0**(-n))-1.0
print (n)
And I've tried to run it but it keeps getting stuck at n=53. Why? I just assumed that while would always be true ...

If you change the last line to print(n, a) you can see what's happening more clearly:
n = 0
a = 1
while a > 0:
n = n + 1
a = (1.0 + 2.0 ** (-n)) - 1.0
print(n, a)
Output:
1 0.5
2 0.25
3 0.125
4 0.0625
# ...
50 8.881784197001252e-16
51 4.440892098500626e-16
52 2.220446049250313e-16
53 0.0
As you can see, a is half the size each time through the loop. Eventually, 2.0 ** (-n) is so small that floating point math (which has limited precision) is unable to tell the difference between 1.0 and 1.0 + 2.0 ** (-n):
>>> 1.0 + 2.0 ** -51
1.0000000000000004
>>> 1.0 + 2.0 ** -52
1.0000000000000002
>>> 1.0 + 2.0 ** -53
1.0
… and when that happens, subtracting 1.0 from 1.0 gives you 0.0, and the while loop terminates.

Related

Why numpy vectorization is slower than a for loop

The below code has two functions that does the same thing: checks to see if the line between two points intersects with a circle.
from line_profiler import LineProfiler
from math import sqrt
import numpy as np
class Point:
x: float
y: float
def __init__(self, x: float, y: float):
self.x = x
self.y = y
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
class Circle:
ctr: Point
r: float
def __init__(self, ctr: Point, r: float):
self.ctr = ctr
self.r = r
def __repr__(self):
return f"Circle(r={self.r}, ctr={self.ctr})"
def loop(p1: Point, p2: Point, circles: list[Circle]):
m = (p1.y - p2.y) / (p1.x - p2.x)
n = p1.y - m * p1.x
max_x = max(p1.x, p2.x)
min_x = min(p1.x, p2.x)
for circle in circles:
if sqrt((circle.ctr.x - p1.x) ** 2 + (circle.ctr.y - p1.y) ** 2) < circle.r \
or sqrt((circle.ctr.x - p2.x) ** 2 + (circle.ctr.y - p2.y) ** 2) < circle.r:
return False
a = m ** 2 + 1
b = 2 * (m * n - m * circle.ctr.y - circle.ctr.x)
c = circle.ctr.x ** 2 + circle.ctr.y ** 2 + n ** 2 - circle.r ** 2 - 2 * n * circle.ctr.y
# compute the intersection points
discriminant = b ** 2 - 4 * a * c
if discriminant <= 0:
# no real roots, the line does not intersect the circle
continue
# two real roots, the line intersects the circle at two points
x1 = (-b + sqrt(discriminant)) / (2 * a)
x2 = (-b - sqrt(discriminant)) / (2 * a)
# check if both points in range
first = min_x <= x1 <= max_x
second = min_x <= x2 <= max_x
if first and second:
return False
return True
def vectorized(p1: Point, p2: Point, circles):
m = (p1.y - p2.y) / (p1.x - p2.x)
n = p1.y - m * p1.x
max_x = max(p1.x, p2.x)
min_x = min(p1.x, p2.x)
circle_ctr_x = circles['x']
circle_ctr_y = circles['y']
circle_radius = circles['r']
# Pt 1 inside circle
if np.any(np.sqrt((circle_ctr_x - p1.x) ** 2 + (circle_ctr_y - p1.y) ** 2) < circle_radius):
return False
# Pt 2 inside circle
if np.any(np.sqrt((circle_ctr_x - p2.x) ** 2 + (circle_ctr_y - p2.y) ** 2) < circle_radius):
return False
# Line intersects with circle in range
a = m ** 2 + 1
b = 2 * (m * n - m * circle_ctr_y - circle_ctr_x)
c = circle_ctr_x ** 2 + circle_ctr_y ** 2 + n ** 2 - circle_radius ** 2 - 2 * n * circle_ctr_y
# compute the intersection points
discriminant = b**2 - 4*a*c
discriminant_bigger_than_zero = discriminant > 0
discriminant = discriminant[discriminant_bigger_than_zero]
if discriminant.size == 0:
return True
b = b[discriminant_bigger_than_zero]
# two real roots, the line intersects the circle at two points
x1 = (-b + np.sqrt(discriminant)) / (2 * a)
x2 = (-b - np.sqrt(discriminant)) / (2 * a)
# check if both points in range
in_range = (min_x <= x1) & (x1 <= max_x) & (min_x <= x2) & (x2 <= max_x)
return not np.any(in_range)
a = Point(x=-2.47496075130008, y=1.3609840363748935)
b = Point(x=3.4637947060471084, y=-3.7779123453298817)
c = [Circle(r=1.2587063082677084, ctr=Point(x=3.618533781361757, y=2.179925931180058)), Circle(r=0.7625751871124099, ctr=Point(x=-0.3173290200183132, y=4.256206636932641)), Circle(r=0.4926043225930364, ctr=Point(x=-4.626312261120341, y=-1.5754603504419196)), Circle(r=0.6026364956540792, ctr=Point(x=3.775240278691819, y=1.7381168262343072)), Circle(r=1.2804597877349562, ctr=Point(x=4.403273380178893, y=-1.6890127555343681)), Circle(r=1.1562415624767421, ctr=Point(x=-1.0675000352105801, y=-0.23952113329203994)), Circle(r=1.112718432321835, ctr=Point(x=2.500137075066017, y=-2.77748519509295)), Circle(r=0.979889574640609, ctr=Point(x=4.494971251199753, y=-1.0530995423779388)), Circle(r=0.7817624050358268, ctr=Point(x=3.2419454348696544, y=4.3303373486692465)), Circle(r=1.0271176198616367, ctr=Point(x=-0.9740272820753071, y=-4.282195116754338)), Circle(r=1.1585218836700681, ctr=Point(x=-0.42096876790888915, y=2.135161027254492)), Circle(r=1.0242603387003988, ctr=Point(x=2.2617850544260767, y=-4.59942951839469)), Circle(r=1.5704233297828027, ctr=Point(x=-1.1182365440831088, y=4.2411408333943506)), Circle(r=0.37137272043983655, ctr=Point(x=3.280499587987774, y=-4.87871834733383)), Circle(r=1.1829610109115543, ctr=Point(x=-0.27755604766113606, y=-3.68429580935016)), Circle(r=1.0993567600839198, ctr=Point(x=0.23602306761027925, y=0.47530122196024704)), Circle(r=1.3865045367147553, ctr=Point(x=-2.537565761732492, y=4.719766182202855)), Circle(r=0.9492796511909753, ctr=Point(x=-3.7047245796551973, y=-2.501817905967274)), Circle(r=0.9866916911482386, ctr=Point(x=1.3021813533479742, y=4.754952371169189)), Circle(r=0.9053004331885084, ctr=Point(x=-3.4912157984801784, y=-0.5269727600532836)), Circle(r=1.3058987272565075, ctr=Point(x=-1.6983878085276427, y=-2.2910189455221053)), Circle(r=0.5342716756987732, ctr=Point(x=4.948676886704507, y=-1.2467089784975183)), Circle(r=1.0603926633240575, ctr=Point(x=-4.390462974765324, y=0.785568745976325)), Circle(r=0.3448422804513971, ctr=Point(x=-1.6459756952994697, y=2.7608629057950362)), Circle(r=0.8521457455807724, ctr=Point(x=-4.503217369041699, y=3.93796926957188)), Circle(r=0.602438849989669, ctr=Point(x=-2.0703406576157493, y=0.6142570312870999)), Circle(r=0.6453692950682722, ctr=Point(x=-0.14802220452893144, y=4.08189682338989)), Circle(r=0.6983361689325062, ctr=Point(x=0.09362196694661651, y=-1.0953438275586391)), Circle(r=1.880331563921456, ctr=Point(x=0.23481661751521776, y=-4.09217120864087)), Circle(r=0.5766225363413416, ctr=Point(x=3.149434524126505, y=-4.639582956406762)), Circle(r=0.6177559628867022, ctr=Point(x=-1.6758918144661683, y=-0.7954935787503492)), Circle(r=0.7347952666955615, ctr=Point(x=-3.1907522890427575, y=0.7048509241855683)), Circle(r=1.2795003337464894, ctr=Point(x=-1.777244415863577, y=2.936422879898364)), Circle(r=0.9181024765780231, ctr=Point(x=4.212544425778317, y=-1.953546993038261)), Circle(r=1.7681384709020282, ctr=Point(x=-1.3702722387909405, y=-1.7013020424154368)), Circle(r=0.5420789771729688, ctr=Point(x=4.063803796292818, y=-3.7159871611415065)), Circle(r=1.3863651881788939, ctr=Point(x=0.7685002210812408, y=-3.994230705171357)), Circle(r=0.5739750223225826, ctr=Point(x=0.08779554290638258, y=4.879912451441914)), Circle(r=1.2019825386919343, ctr=Point(x=-4.206623233886995, y=-1.1617382464768689))]
circle_dt = np.dtype('float,float,float')
circle_dt.names = ['x', 'y', 'r']
np_c = np.array([(x.ctr.x, x.ctr.y, x.r) for x in c], dtype=circle_dt)
lp1 = LineProfiler()
loop_wrapper = lp1(loop)
loop_wrapper(a, b, c)
lp1.print_stats()
lp2 = LineProfiler()
vectorized_wrapper = lp2(vectorized)
vectorized_wrapper(a, b, np_c)
lp2.print_stats()
One implementation is regular for loop implementation, and the other is vectorized implementation with numpy.
From my small knowledge of vectorization, I would have guessed that the vectorized function would yield better result, but as you can see below that is not the case:
Total time: 4.36e-05 s
Function: loop at line 31
Line # Hits Time Per Hit % Time Line Contents
==============================================================
31 def loop(p1: Point, p2: Point, circles: list[Circle]):
32 1 9.0 9.0 2.1 m = (p1.y - p2.y) / (p1.x - p2.x)
33 1 5.0 5.0 1.1 n = p1.y - m * p1.x
34
35 1 19.0 19.0 4.4 max_x = max(p1.x, p2.x)
36 1 5.0 5.0 1.1 min_x = min(p1.x, p2.x)
37
38 6 30.0 5.0 6.9 for circle in circles:
39 6 73.0 12.2 16.7 if sqrt((circle.ctr.x - p1.x) ** 2 + (circle.ctr.y - p1.y) ** 2) < circle.r \
40 6 62.0 10.3 14.2 or sqrt((circle.ctr.x - p2.x) ** 2 + (circle.ctr.y - p2.y) ** 2) < circle.r:
41 return False
42
43 6 29.0 4.8 6.7 a = m ** 2 + 1
44 6 32.0 5.3 7.3 b = 2 * (m * n - m * circle.ctr.y - circle.ctr.x)
45 6 82.0 13.7 18.8 c = circle.ctr.x ** 2 + circle.ctr.y ** 2 + n ** 2 - circle.r ** 2 - 2 * n * circle.ctr.y
46
47 # compute the intersection points
48 6 33.0 5.5 7.6 discriminant = b ** 2 - 4 * a * c
49 5 11.0 2.2 2.5 if discriminant <= 0:
50 # no real roots, the line does not intersect the circle
51 5 22.0 4.4 5.0 continue
52
53 # two real roots, the line intersects the circle at two points
54 1 7.0 7.0 1.6 x1 = (-b + sqrt(discriminant)) / (2 * a)
55 1 4.0 4.0 0.9 x2 = (-b - sqrt(discriminant)) / (2 * a)
56
57 # check if one point in range
58 1 5.0 5.0 1.1 first = min_x < x1 < max_x
59 1 3.0 3.0 0.7 second = min_x < x2 < max_x
60 1 2.0 2.0 0.5 if first and second:
61 1 3.0 3.0 0.7 return False
62
63 return True
Total time: 0.0001534 s
Function: vectorized at line 66
Line # Hits Time Per Hit % Time Line Contents
==============================================================
66 def vectorized(p1: Point, p2: Point, circles):
67 1 10.0 10.0 0.7 m = (p1.y - p2.y) / (p1.x - p2.x)
68 1 5.0 5.0 0.3 n = p1.y - m * p1.x
69
70 1 7.0 7.0 0.5 max_x = max(p1.x, p2.x)
71 1 4.0 4.0 0.3 min_x = min(p1.x, p2.x)
72
73 1 10.0 10.0 0.7 circle_ctr_x = circles['x']
74 1 3.0 3.0 0.2 circle_ctr_y = circles['y']
75 1 3.0 3.0 0.2 circle_radius = circles['r']
76
77 # Pt 1 inside circle
78 1 652.0 652.0 42.5 if np.any(np.sqrt((circle_ctr_x - p1.x) ** 2 + (circle_ctr_y - p1.y) ** 2) < circle_radius):
79 return False
80 # Pt 2 inside circle
81 1 161.0 161.0 10.5 if np.any(np.sqrt((circle_ctr_x - p2.x) ** 2 + (circle_ctr_y - p2.y) ** 2) < circle_radius):
82 return False
83 # Line intersects with circle in range
84 1 13.0 13.0 0.8 a = m ** 2 + 1
85 1 120.0 120.0 7.8 b = 2 * (m * n - m * circle_ctr_y - circle_ctr_x)
86 1 77.0 77.0 5.0 c = circle_ctr_x ** 2 + circle_ctr_y ** 2 + n ** 2 - circle_radius ** 2 - 2 * n * circle_ctr_y
87
88 # compute the intersection points
89 1 25.0 25.0 1.6 discriminant = b**2 - 4*a*c
90 1 46.0 46.0 3.0 discriminant_bigger_than_zero = discriminant > 0
91 1 56.0 56.0 3.7 discriminant = discriminant[discriminant_bigger_than_zero]
92
93 1 6.0 6.0 0.4 if discriminant.size == 0:
94 return True
95
96 1 12.0 12.0 0.8 b = b[discriminant_bigger_than_zero]
97
98 # two real roots, the line intersects the circle at two points
99 1 77.0 77.0 5.0 x1 = (-b + np.sqrt(discriminant)) / (2 * a)
100 1 28.0 28.0 1.8 x2 = (-b - np.sqrt(discriminant)) / (2 * a)
101
102 # check if both points in range
103 1 96.0 96.0 6.3 in_range = (min_x <= x1) & (x1 <= max_x) & (min_x <= x2) & (x2 <= max_x)
104 1 123.0 123.0 8.0 return not np.any(in_range)
For some reason the non vectorized function runs faster.
My simple guess is that it is because the vectorized function runs over the whole array every time and the non vectorized one stops in the middle when it find a circle intersections.
So my questions are:
Is there a numpy function which doesn't iterate over the whole array but stops when the results are false?
What is the reason the vectorized function takes longer to run?
Any general optimization suggestions would be appreciated
Is there a numpy function which doesn't iterate over the whole array but stops when the results are false?
No. This is a long standing feature requested by Numpy users but it will certainly never be added to Numpy. For simple cases, like returning the first index of a boolean array, Numpy could implement that, but the thing is the boolean array needs to be fully created in the first place. In order to support the general case, Numpy should merge multiple operations and do some kind of lazy computation. This basically means rewriting completely Numpy from scratch for an efficient implementation (which is a huge work).
If you need to do that, there are two main solution:
operating on chunks so for the computation to stop early (while computing up to len(chunk) additional items);
writing your own fast compiled implementation using Numba or Cython (with views).
What is the reason the vectorized function takes longer to run?
The input is pretty small and Numpy is not optimized for small arrays. Indeed, each call to a Numpy function typically takes 0.4-4 us on a mainstream processor (like my i5-9600KF). This is because Numpy as many checks to do, new arrays to allocates, generic internal iterators to build, etc. As a result, a line like np.any(np.sqrt((circle_ctr_x - p1.x) ** 2 + (circle_ctr_y - p1.y) ** 2) < circle_radius) doing 8 Numpy calls and creating 7 temporary arrays takes about 8 us on my machine. The second similar line takes the same time. Together, they are already slower than the non-vectorized version.
As pointed out in the question and the comments, the non-vectorized function can stop early and this can also help the non-vectorized version to be even faster than the other.
Any general optimization suggestions would be appreciated
Regarding your code, using Numba (with plain loops and Numpy arrays) is certainly a good idea for performance. Note the first call can be slower due to the compilation time (you can provide the signature to do this at loading time or just use an AOT compiler including Cython).
Note that array of structure are generally not efficient since they prevent the efficient use of SIMD instructions. They are also certainly not efficiently computed by Numpy since the datatype is dynamically created and the Numpy code is already compiled ahead of time (so it cannot implement function for this specific datatype and has to use generic dynamic operation on each item of the array which is significantly slower than basic datatypes). Please consider using structure of arrays. For more information please read this post and more generally this post.

String formatting in general format

Exercise 7.3 from Think Python 2nd Edition:
To test the square root algorithm in this chapter, you could compare it with
math.sqrt. Write a function named test_square_root that prints a table like this:
1.0 1.0 1.0 0.0
2.0 1.41421356237 1.41421356237 2.22044604925e-16
3.0 1.73205080757 1.73205080757 0.0
4.0 2.0 2.0 0.0
5.0 2.2360679775 2.2360679775 0.0
6.0 2.44948974278 2.44948974278 0.0
7.0 2.64575131106 2.64575131106 0.0
8.0 2.82842712475 2.82842712475 4.4408920985e-16
9.0 3.0 3.0 0.0
The first column is a number, a; the second column is the square root of a computed with the function from Section 7.5; the third column is the square root computed by math.sqrt; the fourth column is the absolute value of the difference between the two estimates.
It took me a while to get to this point:
import math
def square_root(a):
x = a / 2
epsilon = 0.0000001
while True:
y = (x + a/x) / 2
if abs(y-x) < epsilon:
break
x = y
return y
def last_digit(number):
rounded = '{:.11f}'.format(number)
dig = str(rounded)[-1]
return dig
def test_square_root():
for a in range(1, 10):
if square_root(a) - int(square_root(a)) < .001:
f = 1
s = 13
elif last_digit(math.sqrt(a)) == '0':
f = 10
s = 13
else:
f = 11
s = 13
print('{0:.1f} {1:<{5}.{4}f} {2:<{5}.{4}f} {3}'.format(a, square_root(a), math.sqrt(a), abs(square_root(a)-math.sqrt(a)), f, s))
test_square_root()
That's my current output:
1.0 1.0 1.0 1.1102230246251565e-15
2.0 1.41421356237 1.41421356237 2.220446049250313e-16
3.0 1.73205080757 1.73205080757 0.0
4.0 2.0 2.0 0.0
5.0 2.2360679775 2.2360679775 0.0
6.0 2.44948974278 2.44948974278 8.881784197001252e-16
7.0 2.64575131106 2.64575131106 0.0
8.0 2.82842712475 2.82842712475 4.440892098500626e-16
9.0 3.0 3.0 0.0
I'm more focused now on achieving the right output, then I'll perfect the code itself, so here are my main problems:
Format the last column (I used {:.12g} once, but then the '0.0' turned to be only '0', so, what should I do?)
Fix the values of the last column. As you can see, there should be only two numbers greater than 0 (when a = 2 and 8), but there are two more (when a = 6 and 1), I printed them alone to see what was going on and the results were the same, I can't understand it.
Thanks for your help! :)

is there an alternative to using mod "%" in python

I am trying to cycle through a list of numbers (mostly decimals), but I want to return both 0.0 and the max number.
for example
maxNum = 3.0
steps = 5
increment = 0
time = 10
while increment < time:
print increment * (maxNum / steps)% maxNum
increment+=1
#
I am getting this as an output
0.0
0.6
1.2
1.8
2.4
0.0
but I want 3.0 as the largest number and to start back at 0.0 I.E.
0.0
0.6
1.2
1.8
2.4
3.0
0.0
Note, I have to avoid logical loops for the calculation part.
You could create the numbers that you want then use itertools.cycle to cycle through them:
import itertools
nums = itertools.cycle(0.6*i for i in range(6))
for t in range(10):
print(next(nums))
Output:
0.0
0.6
1.2
1.7999999999999998
2.4
3.0
0.0
0.6
1.2
1.7999999999999998
Only small change did the trick:
maxNum = 3.0
steps = 5
i = 0
times = 10
step = maxNum / steps
while (i < times):
print(step * (i % (steps + 1)))
i += 1
0.0
0.6
1.2
1.7999999999999998
2.4
3.0
0.0
0.6
1.2
1.7999999999999998
You could make a if statement that looks ahead if the next printed number is 0.0 then print the maxNum
maxNum = 3.0
steps = 5
increment = 0
time = 10
while increment < time:
print(round(increment * (maxNum / steps)% maxNum, 2))
increment+=1
if (round(increment * (maxNum / steps)% maxNum, 2)) == 0.0:
print(maxNum)
0.0
0.6
1.2
1.8
2.4
3.0
0.0
0.6
1.2
1.8
2.4
3.0

why does python display 0 when the result of calculation is less than 1? [duplicate]

This question already has answers here:
Why does the division get rounded to an integer? [duplicate]
(13 answers)
Closed 6 years ago.
i have the following code:
a = 0.0
b = 0.0
c = 1.0
while a < 300:
a = a + 1
b = b + 1
c = c * b
d = (3**a)
e = (a+1)*c
f = d / e
print a, f
The moment f becomes less than 1, I get "0" displayed.. why?
The moment f becomes less than 1, I get "0" displayed
That's not what happens. The first time f is less than 1, 4.0 0.675 is printed. That's not 0:
1.0 1.5
2.0 1.5
3.0 1.125
4.0 0.675
5.0 0.3375
The value of f then quickly becomes very very small, to the point Python starts using scientific notation negative exponents:
6.0 0.144642857143
7.0 0.0542410714286
8.0 0.0180803571429
9.0 0.00542410714286
10.0 0.00147930194805
11.0 0.000369825487013
12.0 8.53443431568e-05
13.0 1.82880735336e-05
14.0 3.65761470672e-06
15.0 6.8580275751e-07
Note the -05, -06, etc. The value of f has become so small that it is more efficient to shift the decimal point. If you were to format those values using fixed-point notation, they'd use more zeros:
>>> format(8.53443431568e-05, '.53f')
'0.00008534434315680000128750276600086976941383909434080'
>>> format(6.8580275751e-07, '.53f')
'0.00000068580275751000002849671038224199648425383202266'
Eventually, f becomes too small for the floating point type; floating point values simply can't go closer to zero beyond this point:
165.0 5.89639287564e-220
166.0 1.05923225311e-221
167.0 1.89148616627e-223
168.0 3.35766775077e-225
169.0 5.92529603077e-227
170.0 0.0
The last value before 0.0 is 5.925 with two hundred and twenty seven zeros before it:
>>> format(5.92529603077e-227, '.250f')
'0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000592529603077000028336751'
That's pretty close to the absolute minimum value a float object can represent; see the min attribute of the sys.float_info named tuple:
>>> import sys
>>> sys.float_info.min
2.2250738585072014e-308
In other words, you reached the limits, and there was no more representable value between 5.92529603077e-227 and 0.0 left.

Differences in w.write between Python 3.2 and 2.6?

I have a function that I use on two different machine one a Mac running Python version 2.6 and the other is a Lenovo running version 3.2.The function writes data to a file and is called from with in a loop. When using Python 3.2 it works as expected and I get output such as below
25.0 25.0 25.0 0
25.0 25.0 75.0 0
25.0 25.0 125.0 0
25.0 25.0 175.0 0
25.0 25.0 225.0 0
25.0 75.0 25.0 0
25.0 75.0 75.0 0
25.0 75.0 125.0 0
25.0 75.0 175.0 0
25.0 75.0 225.0 0
When I run it on the machine running version 2.6 I get this
175.0 25.0 75.0 2
175.0 25.0 125.0 0
25.0 25.0 25.0 0 Should be first line
175.0 25.0 175.0 0
25.0 25.0 75.0 0 Should be second line
175.0 25.0 225.0 0
25.0 25.0 125.0 1
175.0 75.0 25.0 0
25.0 25.0 175.0 1
175.0 75.0 75.0 2
Here is the code
def filesave(Xc,Yc,Zc,S):
Xc = str(Xc)
Yc = str(Yc)
Zc = str(Zc)
Xs = str(S)
#Ms = str(Ma)
w = open("Myout.txt.","a+")
w.write(Xc)
w.write('\t')
w.write(Yc)
w.write('\t')
w.write(Zc)
w.write('\t')
w.write(Xs)
w.write('\n')
w.close()
return()
Is there some difference between the two versions that is causing the difference? Thanks!
EDIT
Rest of Code
def cell_centers():
read_file(F)
dx = dy = dz= float(input('Please enter a value for dr:')) #length of cell side
N = int(input('Please enter a value for N:')) #N^3 Number of cells to be created
Xc = zeros(N) #array creation
Yc = zeros(N)
Zc = zeros(N)
x1=0
y1=0
z1=0
county = 0
countz = 0
for i in range(N): #for loops to define cell centers
Xc[i] = dx/2 +x1
xmin = Xc[i]-dx/2
xmax = Xc[i]+dx/2
x1+=dx #increments x1 positions by dx
for j in range(N):
Yc[j] = dy/2 +y1
ymin = Yc[j]-dy/2
ymax = Yc[j]+dy/2
county+=1
if county==N: #if else statement resets y1 to zero
y1=0
county=0
else:
y1+=dy
for k in range(N):
Zc[k] = dz/2 +z1
countz+=1
zmin = Zc[k]-dz/2
zmax = Zc[k]+dz/2
if countz==N:
z1=0
countz=0
else:
z1+=dz
counter(Xc[i],Yc[j],Zc[k],N,xmin,xmax,ymin,ymax,zmin,zmax,*read_file(F))
return()
def counter(Xc,Yc,Zc,N,xmin,xmax,ymin,ymax,zmin,zmax,Xa,Ya,Za):
Cellcount = zeros(1)
S = (((xmin <= Xa) & (Xa <= xmax))& #count what is in specific range
((ymin <= Ya) & (Ya <= ymax))&
((zmin <= Za) & (Za <= zmax))).sum()
for l in range(1):
Cellcount[l]= S
filesave(Xc,Yc,Zc,S)
return()
I am going to go out on the limb and say the difference you are observing is due to the changed division between version 2.x and 3.x. (it looks like there's a lot of dividing going on, and I can't tell what type the numbers are, integer or float)
In 2.x you would get integer truncation when doing division with integers. This doesn't happen in v 3.x
Python 2
In [267]: 5 / 2
Out[267]: 2
Python 3:
In [1]: 5 / 2
Out[1]: 2.5
Your code does a lot of division.
If you still want to old integer division behavior, you can use // with Python 3:
Python 3:
In [2]: 5 // 2
Out[2]: 2
Changing the Division Operator explains this in detail.
What’s New In Python 3.0 goes over the big changes from v 2 to 3
If you want the new division behavior in Python 2.2+, you can use the from __future__ import division directive (Thanks #Jeff for reminding me).
Python 2:
In [1]: 5 / 2
Out[1]: 2
In [2]: from __future__ import division
In [3]: 5 / 2
Out[3]: 2.5
UPDATE:
Finally, please consider the potential problem of division as a cause (so perhaps the lines aren't out of order, but the results are different due to the division making it only appear that way). Is that possible? Also notice that the 4th column (the 3.x output) has all zeros .. that's not present in the 2.x output and further points toward possible problems with the computation of results -- so in fact the results are different and not out of order.
Your filesave function is fine. I bet the difference in output is because Python 2 returns an integer from integer division expressions, while Python 3 returns a float:
Python 2
>>> 1/2
0
>>> 4/2
2
Python 3
>>> 1/2
0.5
>>> 4/2
2.0
This will give different mathematical results in your program and might account for the different ordering of the output.

Categories

Resources