find the smallest square width but encounter modulo by zero error - python

I code such a function to find the smallest square of an land
def find_smallest(small, big):
if small == big:
return small
else:
sub_small = big % small
sub_big = small
find_smallest(sub_small, sub_big)
but it report error as
>>> find_smallest(640, 1280)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in find_smallest
File "<stdin>", line 5, in find_smallest
ZeroDivisionError: integer division or modulo by zero
There is not a modulo by zero error.
What's the problem?

Consider find_smallest(2,8).
In the first loop you set sub_small = big % small = 8 % 2 = 0 and sub_big = small = 2. Then you call find_smallest(0,2).
In the second loop you then try to do sub_small = big % small = 2 % 0 which you cant do.

Related

Programming a distance

First of all: I am by no means a Python expert, so this question is probably rather easy. Secondly, I worked over more than 2 hours on this and now I've decided I needed help. I want to implement a distance in Python. The distance is given as follows:
Where ui and uj are vectors that are given. d is the dimension of that vector. For example: if ui = (1,2,3), then ui_0= 1.
Now, this is what I've come up with so far: (here, xi = ui and xj = uj)
def dist(xi, xj, k):
distances = np.zeros(len(xi))
min1 = (0, 0)
min2 = (0, 0)
for dim in [0, len(xi)]:
for s in [-k, k]:
min1 = abs(xi[dim] - xj[dim + s])
min1[-k, k].min()
min2 = min(abs(xj[dim] - xi[dim + s]))
min2[-k, k].min()
distances = max(min1,min2)
but it doesn't work. Does anybody know where I've gone wrong?
Traceback:
Traceback (most recent call last): File "<input>", line 1, in
<module> File "<input>", line 8, in dist IndexError: invalid index
to scalar variable.
EDIT:
Ok, I tried to look at the case where k is maximal and I've taken the comments of Riley and Wouda into account. I came up with this piece of code:
def dist1(xi, xj):
for dim in range(len(xi)):
for s in range(-dim, len(xi) - dim):
return max(min(abs(xi[dim] - xj[dim + s])), min(abs(xj[dim] - xi[dim + s])))
and I still get the error:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 4, in dist1
TypeError: 'numpy.int64' object is not iterable
What is going on?
You appear to forget d is a parameter also (since you compute Dist_d^{ij}, where d is clearly a passed parameter). Together with k, I think the following represents the snippet of math you posted.
def dist(xi, xj, d, k):
min1 = min(abs(xi[d] - xj[d + s]) for s in range(-k, k + 1))
min2 = min(abs(xj[d] - xi[d + s]) for s in range(-k, k + 1))
return max(min1, min2)
Notice that Python will index negative values from the end of the list, which may or may not be what you want (in math, generally, not). So getting the arguments to this function right is a bit tricky, and you should build-in some checks to make sure all cases are handled correctly.

Strange if statement

I found this strange if-statement in somebody else’s code:
if variable & 1 == 0:
I don't understand it. It should have two ==, right?
Can somebody explain this?
The conditional is a bitwise operator comparison:
>>> 1 & 1
1
>>> 0 & 1
0
>>> a = 1
>>> a & 1 == 0
False
>>> b = 0
>>> b & 1 == 0
True
As many of the comments say, for integers this conditional is True for evens and False for odds. The prevalent way to write this is if variable % 2 == 0: or if not variable % 2:
Using timeit we can see that there isn't much difference in performance.
n & 1("== 0" and "not")
>>> timeit.Timer("bitwiseIsEven(1)", "def bitwiseIsEven(n): return n & 1 == 0").repeat(4, 10**6)
[0.2037370204925537, 0.20333600044250488, 0.2028651237487793, 0.20192503929138184]
>>> timeit.Timer("bitwiseIsEven(1)", "def bitwiseIsEven(n): return not n & 1").repeat(4, 10**6)
[0.18392395973205566, 0.18273091316223145, 0.1830739974975586, 0.18445897102355957]
n % 2("== 0" and "not")
>>> timeit.Timer("modIsEven(1)", "def modIsEven(n): return n % 2 == 0").repeat(4, 10**6)
[0.22193098068237305, 0.22170782089233398, 0.21924591064453125, 0.21947598457336426]
>>> timeit.Timer("modIsEven(1)", "def modIsEven(n): return not n % 2").repeat(4, 10**6)
[0.20426011085510254, 0.2046220302581787, 0.2040550708770752, 0.2044820785522461]
Overloaded Operators:
Both the % and & operators are overloaded.
The bitwise and operator is overloaded for set. s.intersection(t) is equivalent to s & t and returns a "new set with elements common to s and t".
>>> {1} & {1}
set([1])
This doesn't effect our conditional:
>>> def bitwiseIsEven(n):
... return n & 1 == 0
>>> bitwiseIsEven('1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in bitwiseIsEven
TypeError: unsupported operand type(s) for &: 'str' and 'int'
>>> bitwiseIsEven({1})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in bitwiseIsEven
TypeError: unsupported operand type(s) for &: 'set' and 'int'
The modulo operator will also throw TypeError: unsupported operand type(s) for most non-ints.
>>> def modIsEven(n):
... return n % 2 == 0
>>> modIsEven({1})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in modIsEven
TypeError: unsupported operand type(s) for %: 'set' and 'int'
It is overloaded as a string interpolation operator for the old %-formatting. It throws TypeError: not all arguments converted during string formatting if a string is used for the comparison.
>>> modIsEven('1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in modIsEven
TypeError: not all arguments converted during string formatting
This won't throw if the string includes a valid conversion specifier.
>>> modIsEven('%d')
False
This code just checks if the lowest bit of variable is a 0. Based on operator precedence this is:
if (variable & 1) == 0:
First AND the lowest bit with one (extract just the lowest bit), then check if it is 0.
The & is a bitwise operator. It returns an integer with 1 bit for every bit of its two operands that are both 1, and 0 in all other places. For example:
a = 10 # 0b1010
b = 6 # 0b0110
a & b # 0b0010
Now, if you have variable & 1, you're comparing variable against 0b1 which will only return 1 if that last digit in the binary representation is a 1, otherwise a 0.
Your only concern is probably the operator &. It is a bitwise and which takes the binary format of the two operands and perform "logic and" on each pair of bits.
For your example, consider the following:
variable = 2 #0b0010
if variable & 1 == 0:
print "condition satisfied" # satisfied, 0b0010 & 0b0001 = 0
variable = 5 #0b0101
if variable & 1 == 0:
print "condition satisfied" # not satisfied, 0b0101 & 0b0001 = 1
Note:
variable = 6 #0b0110
if variable & 2 == 0:
print "condition satisfied" # not satisfied, 0b0110 & 0b0010 = 2 (0b0010)

TypeError in Decimal module: integer argument expected, got float

I am quite new to the Python language, and for my first exercise I wanted to make a script that calculates the constant e.
To do this, I defined a function calc_temp which would have a variable temp and temp would start off equal to one. I would then multiply temp by the quotient of 1 and a variable called e_num I would then add temp to a variable approx_e.
Then, I used a while True: loop to perform the function indefinitely.
The code looks like this:
#!/usr/bin/python
import math
from decimal import *
temp = 1
approx_e = Decimal(1)
e_num = 1
def calc_temp(e_num):
global approx_e
global temp
len_ = math.log10(math.factorial(e_num))
getcontext().prec = len_
temp = Decimal(temp * 1 / e_num)
e_num = e_num + 1
approx_e = approx_e + temp
return approx_e
while True:
calc_temp(e_num)
However, when I execute the script, it raises the following TypeError:
Traceback (most recent call last):
File "/home/dorian/Desktop/ever3.py", line 17, in <module>
calc_temp(e_num)
File "/home/dorian/Desktop/ever3.py", line 14, in calc_temp
approx_e = approx_e + temp
File "/usr/lib/python2.7/decimal.py", line 1209, in __add__
ans = ans._fix(context)
File "/usr/lib/python2.7/decimal.py", line 1692, in _fix
changed = rounding_method(self, digits)
File "/usr/lib/python2.7/decimal.py", line 1771, in _round_half_even
if _exact_half(self._int, prec) and \
TypeError: integer argument expected, got float
I tried changing the type of the variables, making them Decimals, integers, and floating point numbers, but it still raises the error. What could be causing it?
You are setting the context precision to a float:
len_ = math.log10(math.factorial(e_num))
getcontext().prec = len_
Set it to an integer:
getcontext().prec = int(len_)
Quoting the decimal.Context() documentation:
The prec field is a positive integer that sets the precision for arithmetic operations in the context.

Math domain error in fermat

from math import sqrt
def fermatBook (n):
x=int(sqrt(n))
c=x**2-n
while (sqrt(c)!=int(sqrt(c))):
x=x+1
y=sqrt(c)
a=x+y
b=x-y
if a==1 or b==1:
print "The number is prime"
return a, b
error:
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
fermatBook (23867)
File "C:/Python27/fermatLivro.py", line 6, in fermatBook
while (sqrt(c)!=int(sqrt(c))):
ValueError: math domain error
I don't know what is going wrong with the program... Could someone help me ?
most likely your variable c is going negative:
Example
if you call:
n = 2
fermatBook(n)
it will assign the following values to the following variables:
x = int(sqrt(n)) = int(1.47...) = 1
c = x**2 - n = 1**2 - 2 = 1 - 2 = -1
This will likely happen alot on values of n whose square root is not an integer.
sqrt(n) >= int(sqrt(n)), n >= 0
Then when you call sqrt(c) it is out of the domain because it cannot handle negative values.
>>> from math import sqrt
>>> sqrt(-1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error
You should rather use something that can handle imaginary numbers, i.e. cmath
Or perform checks to assure this does not happen:
As an example...
if c < 0:
c = 0
As soon as you fix this however you are going to run into another problem:
This is an infinite loop:
while (sqrt(c)!=int(sqrt(c))):
x=x+1
you need to update c otherwise the condidtion will never change no matter how many times you increment x. You probably meant this?
while (sqrt(c)!=int(sqrt(c))):
x=x+1
c = x**2+n # <--- UPDATE c

What does "TypeError: 'float' object cannot be interpreted as an integer" mean when using range?

I don't understand why I can't use my variable c.
code:
from turtle import *
speed(0)
hideturtle()
c = 450
def grid(x,y,a):
seth(0)
pu()
goto(x,y)
pd()
for i in range(4):
forward(a)
rt(90)
for i in range(c/10):
seth(0)
forward(10)
rt(90)
forward(c)
backward(c)
for i in range(c/10):
seth(0)
rt(90)
forward(10)
rt(90)
forward(c)
backward(c)
pu()
goto(a+10,0)
write("x")
goto(0,a+10)
write("y")
pd()
grid(0,0,c)
grid(-c,0,c)
grid(-c,c,c)
grid(0,c,c)
I get the following error message:
Traceback (most recent call last):
File "C:\Users\nick\Desktop\gridv2.py", line 35, in <module>
grid(0,0,c)
File "C:\Users\nick\Desktop\gridv2.py", line 15, in grid
for i in range(c/10):
TypeError: 'float' object cannot be interpreted as an integer
In:
for i in range(c/10):
You're creating a float as a result - to fix this use the int division operator:
for i in range(c // 10):
range() can only work with integers, but dividing with the / operator always results in a float value:
>>> 450 / 10
45.0
>>> range(450 / 10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'float' object cannot be interpreted as an integer
Make the value an integer again:
for i in range(int(c / 10)):
or use the // floor division operator:
for i in range(c // 10):
As shown below, range only supports integers:
>>> range(15.0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: range() integer end argument expected, got float.
>>> range(15)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>>
However, c/10 is a float because / always returns a float.
Before you put it in range, you need to make c/10 an integer. This can be done by putting it in int:
range(int(c/10))
or by using //, which returns an integer:
range(c//10)
It is also possible to fix this with np.arange() which works for float numbers, instead of range:
import numpy as np
for i in np.arange(c/10):

Categories

Resources