Why has my program "stopped" working? - python

I made a program to calculate pi (just as a bit of fun, I don't want to use the pi that's built in) in Python 3.3.2. It works fine - it gets the correct value of pi up to 7 decimal places. However, once it gets to this point, the program continues but the values do not change. I have tried using decimal.Decimal, but it does not work - it comes up with the following error:
TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'float'
This is my working code (using floats instead of decimals.) I have only included the actual algorithm :
pi=float(3)
a=2
b=0
c=float(0)
while 1==1:
b=a*(a+1)*(a+2)
c=4/b
pi=pi+c
print(str(pi))
a=a+2
b=a*(a+1)*(a+2)
c=4/b
pi=pi-c
print(str(pi))
a=a+2
And this is the result:
http://i.imgur.com/y0qgBMB.png (sorry, I don't have enough reputation to post images directly)
Please note that the program actually stopped working much earlier than this, I just left it there for a while.
I know that the algorithm that I am using is capable of finding pi to many more decimal places, so can someone please tell me why it is not working, and give me any possible solutions?
As you might notice from the simplicity of my code that I am not too good at python - only the basic knowledge that I have been taught at school. Simple solutions would be much appreciated!
EDIT
This is the non-working code with Decimal, and Jasper's suggestion in it.
import decimal
pi=decimal.Decimal(3)
a=2
b=0
c=decimal.Decimal(0)
while True:
b=a*(a+1)*(a+2)
c=4/b
pi=pi+c
print(str(pi))
a=a+2
b=a*(a+1)*(a+2)
c=4/b
pi=pi-c
print(str(pi))
a=a+2
This is the error:
Traceback (most recent call last):
File "C:\Users...\fastpi2.py", line 9, in
pi=pi+c TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'float'

Your code fails because the division of two integers results in a float (in Python 3):
>>> from decimal import Decimal
>>> pi = Decimal(3)
>>> a=2
>>> b=a * (a+1) * (a+2)
>>> c=4/b
>>> type(c)
<class 'float'>
>>> pi = pi + c
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'Decimal' and 'float'
The following works:
>>> a = Decimal(2)
>>> one = Decimal(1)
>>> b = a * (a+one) * (a+one+one)
>>> c = Decimal(4) / b
>>> type(c)
<class 'decimal.Decimal'>
>>> pi = pi + c
>>> pi
Decimal('3.166666666666666666666666667')

Related

TypeError: unsupported operand type. How to to find the smallest difference between numbers in a list

i need to find the smallest difference between numbers in a list.
For some reason it doesnt work when i input numbers in the console, and i get this error TypeError: unsupported operand type(s) for -: 'str' and 'str'
def najmanja_razlika(): #smallest_diff
a=input('unesite brojeve liste')
b=len(a)
razlika=10**20 #difference
for i in range(b-1):
for j in range(i+1,b):
if int(abs(a[i]-a[j]))<razlika:
razlika=abs(a[i]-a[j])
return razlika
print(str(najmanja_razlika()))
What i get when i run this is:
unesite brojeve liste5,4,9,3
Traceback (most recent call last):
File "C:/Users/Nina/PycharmProjects/klkOR/klk4.py", line 19, in <module>
print(str(najmanja_razlika()))
File "C:/Users/Nina/PycharmProjects/klkOR/klk4.py", line 11, in najmanja_razlika
if int(abs(a[i]-a[j]))<razlika:
TypeError: unsupported operand type(s) for -: 'str' and 'str'
You did not convert the string input into an int or float, you might like to do something like this.
def najmanja_razlika(): #smallest_diff
a=[int(i) for i in input('unesite brojeve liste').split(',')]
b=len(a)
razlika=10**20 #difference
for i in range(b-1):
for j in range(i+1,b):
if int(abs(a[i]-a[j]))<razlika:
razlika=abs(a[i]-a[j])
return razlika
print(str(najmanja_razlika()))
Also, note that indentation matters in Python.
This is the output that I obtained:
unesite brojeve liste5,4,2,9,6
1
By the way, if you sort your vector first, you reduce the complexity from O(n^2) to O(nlogn).
If you have numpy installed you could use it to efficiently compute the minimum difference (it is always faster than pure Python loops). I would also use json (part of the standard library, no need to install it) to parse the input string.
import json
import numpy as np
def min_difference():
input_string = '[' + input('Enter comma-separated numbers: ') + ']'
a = np.array(json.loads(input_string))
mask = ~np.eye(a.shape[0], dtype=bool)
return np.abs(a[:, None] - a[None, :])[mask].min()

New, unexpected operand error with # operator with ndarray or matrix operands

I have been able to use # to do matrix multiplication before, but for some reason, it is not working anymore. I'm running Python 3.5.4, and in either IPython 6.2.1 or notebook 5.0.0, this unexpected error comes up:
In [1]: from numpy import arange
In [2]: A = arange(5)
In [3]: B = arange(15).reshape((5,3))
In [4]: A # B
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-455d622f3b50> in <module>()
----> 1 A # B
TypeError: unsupported operand type(s) for #: 'numpy.ndarray' and 'numpy.ndarray'
Using the matrix type doesn't help:
In [5]: from numpy import matrix
In [6]: A = matrix(arange(5))
In [7]: B = matrix(arange(15).reshape((5,3)))
In [8]: A # B
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-8-455d622f3b50> in <module>()
----> 1 A # B
TypeError: unsupported operand type(s) for #: 'matrix' and 'matrix'
I'm at a total loss here. Is the # operator deprecated? Am I missing something obvious? This came up while I was revising a notebook that worked fine about a year ago. Is there some other information that would help diagnose whatever is going on?
As far as I can tell, it turns out to have been an issue with having the right version of numpy, per cxw's comment. I have updated numpy, and everything seems to be working fine now.

Modulo large prime - TypeError: unsupported operand type(s) for %: 'int' and 'str'

I am trying to partition a large string F to m blocks as follows:
import random
from largeprimes import generateRandom
def generateRandom(length):
t = random.randint(0, 2**length)
str = "{0:b}".format(t)
if (len(str) < length):
str.zfill(length)
return str
def divide_file_block (): #return bi: int
b = []
for i in range (0, m):
b_i = F[(i*blocklen) : ((i+1)* blocklen)]
temp = int(b_i, 2) % q
b.append(temp)
return b
F = generateRandom(102400)
m = 100
blocklen = len(F)/m
q = generateLargePrime(1024) # generateLargePrime is from https://langui.sh/2009/03/07/generating-very-large-primes/
print divide_file_block ()
Note: you shall copy the code from 1 to the current directory, remove the last print statement there and name it largpeprimes.py. This makes the generateLargePrime function importable.
When I test on a small example, it printed out correct result. But when I test on b_i and q having 1024 bits, it printed out the error:
temp = int(b_i, 2) % q
TypeError: unsupported operand type(s) for %: 'int' and 'str'
Could you please explain me why and give me a suggestion to show this problem. Thanks in advance.
The function generateLargePrime sometime returns string
Trying the code I run into the same problem.
Testing it in debugger I got the cause: q has a value of `'Failure after 1100.0 tries.'
This is definitely a string an causes the failures.
I would recommend modifying the generateLargePrime code to throw an exception instead of reporting the failure by returned value.
Few tips for detecting this kind of problems
print out the problematic value
This is the simplest (and probably most popular) quick solution.
something like
b_i = F[(i*blocklen) : ((i+1)* blocklen)]
print "q", q # here is all the magic
temp = int(b_i, 2) % q
would tell you the value
place assert into your code
b_i = F[(i*blocklen) : ((i+1)* blocklen)]
assert isinstance(q, int)
temp = int(b_i, 2) % q
would throw an exception as soon as q is not of type int
run the code in debugger
pdb comes with Python, I prefer ipdb which comes with IPython, both would help you.
have the failing code written as a script
Try to run it via Python interpreter
$ python failingscript.py
as it fails, you simply try once more, but instead of python use pdb or ipdb
$ ipdb failingscript.py
the debugger let you control running the code line by line. Usually I let it run by "c" (continue) command and it soon crashes at the problematic point. Then I use "l" (list) to see, what line of code we are at, and finally use "p" (print) command to print values of variables, which are making problems. This way I used "p q" and found, it is a string.
It takes a moment to learn pdb or ipdb, but it works as turbo resolver so it is definitely the skill to learn. Great tutorial is at PMotW

Float value is equal -1.#IND

A function returns a list which contains of float values. If I plot this list, I see that some of the float values are equal -1.#IND. I also checked the type of those -1.#IND values. And they are also of float type.
But how can I understand this -1.#IND values? What do they represent or stand for?
-1.#IND means indefinite, the result of a floating point equation that doesn't have a solution. On other platforms, you'd get NaN instead, meaning 'not a number', -1.#IND is specific to Windows. On Python 2.5 on Linux I get:
>>> 1e300 * 1e300 * 0
-nan
You'll only find this on python versions 2.5 and before, on Windows platforms. The float() code was improved in python 2.6 and consistently uses float('nan') for such results; mostly because there was no way to turn 1.#INF and -1.#IND back into an actual float() instance again:
>>> repr(inf)
'1.#INF'
>>> float(_)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for float(): 1.#INF
>>> repr(nan)
'-1.#IND'
>>> float(_)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for float(): -1.#IND
On versions 2.6 and newer this has all been cleaned up and made consistent:
>>> 1e300 * 1e300 * 0
nan
>>> 1e300 * 1e300
inf
>>> 1e300 * 1e300 * -1
-inf

Python integer issues

EDIT: SOLVED--SOURCE CODE HERE: http://matthewdowney20.blogspot.com/2011/09/source-code-for-roku-remote-hack.html
thanks in advance for reading and possibly answering this. So I have a slice of code that looks like this (the commands Down() Select() and Up() are all predefined):
def c1(row):
row_down = row
row_up = row
while row_down > '1':
Down()
row_down = row_down - 1
time.sleep(250)
Select()
time.sleep(.250)
while row_up > '1':
Up()
row_up = row_up - 1
time.sleep(250)
So when I run this with either c1('3') or c1(3) (not jut 3, any number does this) it stops responding, no error or anything, but it executes the first Down() command, and it doesnt seem to get past the row_down = row_down - 1 . So i figure maybe it is stuck on time.sleep(.250), because it isnt executing the Select(), so if i remove time.sleep(.250) from the code i get an error like this:
Traceback (most recent call last):
File "test.py", line 338, in <module>
c1('3')
File "test.py", line 206, in c1
row_down = row_down - 1
TypeError: unsupported operand type(s) for -: 'str' and 'int'
this code snippet is part of a larger program designed for controlling the roku player from a computer, and so far everything has worked but this, which is to automate the typing in the search field, so that you do not have to continually scroll until you find a letter and select. c1(row) would be column 1 row x, if any of you would like the source code for the program over all, i would be happy to send it out. Anyway thanks for listening.
Perhaps you meant
while row_down > 1:
(note 1 is written without quotes). If so, call c1 with c1(3) not c1('3').
Also, in CPython (version 2, but not version 3) integers are comparable to strings, but the answer is not what you might expect:
3 > '1'
# False
When comparing any integer to any string, the integer is always less than string because (believe it or not!) i (as in integer) comes before s (as in string) in the alphabet.
As TokenMacGuy has already pointed out, addition of integers with strings raises a TypeError:
'3' - 1
# TypeError: unsupported operand type(s) for +: 'int' and 'str'
This might explain the error you are seeing when calling c1('3').
>>> x = raw_input('enter a number: ')
enter a number: 5
>>> x
'5'
>>> type(x)
<type 'str'>
>>> x + 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
>>> type(int(x))
<type 'int'>
>>> int(x) + 5
10
>>>
(if you're using python3, use input instead of raw_input)
I suspect that the loop is running with out error because you can subtract from a character to change it: "b - 1 = a". (read edit) It also doesn't error is because, like Marcelo Cantos said in his comment, the first time.sleep is for 250 seconds, not .250 seconds. The error when you remove the time.sleep might be coming up when you subtract past the the ASCII character range since it runs through the loop a lot quicker without the time.sleep.
I hope that helps!
Edit: Actually, I think what I said works in C or something. In python, it doesn't work. The other stuff I said might shed some light though!

Categories