Why does this Python code give me the wrong answer? - python

I wrote a simple Python code to solve a certain Hydraulic formula (The Manning's equation):
import math
def mannings(units,A,P,S,n):
if units=='SI':
k=1.0
elif units=='US':
k=1.49
R=A/P
V=(k/n)*(math.pow(R,(2/3)))*(math.sqrt(S))
Q=A*V
return R,V,Q
In the code above, the velocity V is calculated from the k, n, R and S. The velocity is then used to calculate the discharge Q by multiplying with Area A. The user inputs the unit convention, the A, P, S and n. k is decided on the basis of unit convention.
When I run the function using mannings('US',1.0618,2.7916,0.02,0.015), I get (0.38035535176959456, 14.047854719572745, 14.916012141242343). The R value matches the R calculated in a spreadsheet, but the V and Q are way off. The actual V should be 7.374638178
and the Q should be 7.830634155.
It'd be great if someone can tell me what's going wrong here. This is a pretty straightforward formula and I was guessing it should work easily.

Your problem is that 2/3 is an integer division and therefore evaluates to 0. You want 2.0/3 to force a floating-point division. Or else include from __future__ import division at the top of your file to use the Python 3-style division in Python 2.x.
Assuming you don't use the __future__ solution, you will also want to write your R = A / P as e.g. R = float(A) / P because otherwise, if A and P are both integers, R will also be an integer.

Related

Python round calculator

Hey i'm a little noob still but i'm playing around with python and i want to round D to it's nearest decimal, C and H are fixed and D is the rawinput, the whole answer should be rounded but i keep getting decimals,i want this formula :
Q = Square root of [(2 * C * D)/H]
her's my code:*
import math
C=50
H=30
D=int(raw_input())
a=int(round(D))
Q= math.sqrt(2*C*a/H)
print Q
if i enter 100 i get 18.24
i just want it to be 18
i would really appreciate your help, thanks
import math
C = 50
H = 30
a = int(raw_input())
# prints as a float
# Q = round(math.sqrt(2 * C * a / H), 0)
# prints as an int
Q = int(round(math.sqrt(2 * C * a / H), 0))
print Q
Your code appears to be rounding in the wrong place. You're rounding the input a, which was already the integer D. You're not rounding the result of the square root Q, which is a float.
Note that you're code actually has an extra rounding step you may not intend in it. When you divide two integers in Python 2, you'll get another integer, even if the computation should have had a remainder. You get floor division, always rounding towards negative infinity, not to the nearest integer (so e.g. 9/10 is 0). In your code, 2*C*a is an integer, since all values you're multiplying are, and so when you divide by h (another integer), it's going to round the division off. In the case you gave where you entered 100 as the user input, you'll get 333 as the result of the division instead of the more precise 333.3333333333333. This in turn makes your square root calculation give a different value (18.24828759089466 instead of 18.257418583505537).
Anyway, you probably want to use floating point values everywhere except maybe at the end when you round off the value before printing it. You almost certainly don't want to be using integer math by accident as your current code does. One way to do that is to turn one of your constant values into a float, and move the rounding to the end:
C=50.0 # make the calculations use floats, rather than ints
H=30
D=int(raw_input()) # no need for `a` anymore, we're rounding later instead
Q= int(round(math.sqrt(2*C*D/H))) # round after taking the square root, not before
An alternative to using C=50.0 is to put from __future__ import division at the top of your file, which tells Python that you want division between integers to return a float. That's the default behavior in Python 3, and it's much nicer most of the time. If you specifically want "floor" division, you can explicitly ask for it with the // operator. You might also consider actually using Python 3, rather than making do with Python 2's forwards compatibility features.

Python modulo result differs from wolfram alpha?

When I run my python 3 program:
exp = 211
p = 199
q = 337
d = (exp ** (-1)) % ((p - 1)*(q - 1))
results in 211^(-1).
But when I run the calculation in wolfram alpha I get the result I was expecting.
I did some test outputs and the variables exp, p and q in the program are all the integer values I used in wolfram alpha.
My goal is to derive a private key from a (weakly) encrypted integer.
If I test my wolfram alpha result, I can decrypt the encrypted message correctly.
Wolfram Alpha is computing the modular inverse. That is, it's finding the integer x such that
exp*x == 1 mod (p - 1)*(q - 1)
This is not the same as the modulo operator %. Here, Python is simply calculating the remainder when 1/exp is divided by (p - 1)*(q - 1) when given the expression in your question.
Copying the Python code from this answer, you can compute the desired value with Python too:
>>> modinv(exp, (p - 1)*(q - 1))
45403
Wolfram Alpha does not have well-defined syntax. It takes arbitrary text you provide and attempts to figure out what you meant by that input. In this case, it decided you were probably looking for a modular inverse, and it gave you one.
Python has well-defined syntax. In Python, the parser does not take the ** and the % together and guess that that combination makes the two operators have a meaning other than their usual meaning. The ** is computed the usual way, and then % is the modulo operator. If you want a modular inverse, you'll have to write one yourself.
I think the idea here is that wolfram alpha and python define the modulo operation differently depending on the fact that you are dealing with integers or real numbers.
In this case, Wolfram Alpha is using the modulo inverse because it detects the first number is 0 < x < 1
More information about the definition on real numbers here
Python evaluates immediately (211^(-1) gets computed as 0.004739... and not ekpt as 1/211) and the modular Euclidan remainder for x and y is conventinally defined as x-floor(x/y)*y if any of x,y is a rational number. If you do your calculation with some dedicated number theoretic program like e.g.: GP/Pari
ep = 211;p = 199;q = 337;(ep ^ (-1)) % ((p - 1)*(q - 1))
you will get the result you expected to get because a) it keeps fractions as fractions as long as possible and b) knows about modular arithmetic.
Is you like Python you may take a look at the programms an libraries offered at SciPy. SymPy might be what you are looking for.

python strange result using math.fmod()

I am playing around with the math module in Python 3.4 and I got some curious results when using fmod function for which I am having hard times in getting detailed info from the python website.
One simple example is the following:
from math import *
x = 99809175801648148531
y = 6.5169020832937505
sqrt(x)-cos(x)**fmod(x, y)*log10(x)
it returns:
(9990454237.014296+8.722374238018135j)
How to interpret this result? What is j?
Is it an imaginary number like i?
If so, why j and not i?
Any info, as well as links to some resources about fmod are very welcome.
The result you got was a complex number because you exponentiated a negative number. i and j are just notational choices to represent the imaginary number unit, i being used in mathematics more and j being used in engineering more. You can see in the docs that Python has chosen to use j:
https://docs.python.org/2/library/cmath.html#conversions-to-and-from-polar-coordinates
Here, j is the same as i, the square root of -1. It is a convention commonly used in engineering, where i is used to denote electrical current.
The reason complex numbers arise in your case is that you're raising a negative number to a fractional power. See How do you compute negative numbers to fractional powers? for further discussion.
cos(x) is a negative number. When you raise a negative number to a non-integral power, it is not surprising to get a complex result. Most roots of negative numbers are complex.
>>> x = 99809175801648148531
>>> y = 6.5169020832937505
>>> cos(x)
-0.7962325418899466
>>> fmod(x,y)
3.3940870272073056
>>> cos(x)**fmod(x,y)
(-0.1507219382442201-0.436136801343955j)
Imaginary numbers can be represented with either an 'i' or a 'j'. I believe the reasons are historical. Mathematicians prefered 'i' for imaginary. Electrical engineers didn't want to get an imaginary 'i' confused with an 'i' for current, so they used 'j'. Now, both are used.

Python - how to compute all nth roots of a number?

Is it possible to calculate n complex roots of a given number using Python? I've shortly checked it, and it looks like Python gives me wrong/incomplete answers:
(-27.0j)**(1.0/3.0) produces (2.598076211353316-1.4999999999999998j)
but proper roots should be 3 complex numbers, because every non-zero number has n different complex number nth roots. Is it possible in Python?
I don't think standard Python will do this unless you write a function for it, but you can do it with Numpy:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.roots.html
There are many multi-valued complex functions - functions that can have more than one value corresponding to any point in their domain. For example: roots, logarithms, inverse trigonometric functions...
The reason these functions can have multiple values is usually because they are the inverse of a function that has multiple values in the domain map to the same value.
When doing calculations with such functions, it would be impractical to always return all possible values. For the inverse trigonometric functions, there are infinitely many possible values.
Usually the different function values can be expressed as a function of an integer parameter k. For example, the values of log z with z = r*(cos t + i*sin t is log r + i*(t + k*2*pi) with k any integer. For the nth root, it is r**(1/n)*exp(i*(t+k*2*pi)/n with k=0..n-1 inclusive.
Because returning all possible values is impractical, mathematical functions in Python and almost all other common programming languages return what's called the 'principal value' of the function. (reference) The principal value is usually the function value with k=0. Whatever choice is made, it should be stated clearly in the documentation.
So to get all the complex roots of a complex number, you just evaluate the function for all relevant values of k:
def roots(z, n):
nthRootOfr = abs(z)**(1.0/n)
t = phase(z)
return map(lambda k: nthRootOfr*exp((t+2*k*pi)*1j/n), range(n))
(You'll need to import the cmath module to make this work.) This gives:
>>> roots(-27j,3)
[(2.59808-1.5j), (1.83691e-16+3j), (-2.59808-1.5j)]
If you want to get all roots on clean python you can create simple function to do this:
import math
def root(num, r):
base = num ** (1.0/r)
roots = [base]
for i in range(1, r):
roots.append(complex(base * math.cos(2*math.pi * i / r), base * math.sin(2*math.pi * i / r)))
return roots

Binomial test in Python for very large numbers

I need to do a binomial test in Python that allows calculation for 'n' numbers of the order of 10000.
I have implemented a quick binomial_test function using scipy.misc.comb, however, it is pretty much limited around n = 1000, I guess because it reaches the biggest representable number while computing factorials or the combinatorial itself. Here is my function:
from scipy.misc import comb
def binomial_test(n, k):
"""Calculate binomial probability
"""
p = comb(n, k) * 0.5**k * 0.5**(n-k)
return p
How could I use a native python (or numpy, scipy...) function in order to calculate that binomial probability? If possible, I need scipy 0.7.2 compatible code.
Many thanks!
Edited to add this comment: please note that, as Daniel Stutzbach mentions, the "binomial test" is probably not what the original poster was asking for (though he did use this expression). He seems to be asking for the probability density function of a binomial distribution, which is not what I'm suggesting below.
Have you tried scipy.stats.binom_test?
rbp#apfelstrudel ~$ python
Python 2.6.2 (r262:71600, Apr 16 2009, 09:17:39)
[GCC 4.0.1 (Apple Computer, Inc. build 5250)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from scipy import stats
>>> print stats.binom_test.__doc__
Perform a test that the probability of success is p.
This is an exact, two-sided test of the null hypothesis
that the probability of success in a Bernoulli experiment
is `p`.
Parameters
----------
x : integer or array_like
the number of successes, or if x has length 2, it is the
number of successes and the number of failures.
n : integer
the number of trials. This is ignored if x gives both the
number of successes and failures
p : float, optional
The hypothesized probability of success. 0 <= p <= 1. The
default value is p = 0.5
Returns
-------
p-value : float
The p-value of the hypothesis test
References
----------
.. [1] http://en.wikipedia.org/wiki/Binomial_test
>>> stats.binom_test(500, 10000)
4.9406564584124654e-324
Small edit to add documentation link: http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.binom_test.html#scipy.stats.binom_test
BTW: works on scipy 0.7.2, as well as on current 0.8 dev.
Any solution that looks like comb(n, k) * 0.5**k * 0.5**(n-k) isn't going to work for large n. On most (all?) platforms, the smallest value a Python float can store is around 2**-1022. For large n-k or large k, the right-hand side will get rounded to 0. Likewise, comb(n, k) can grow so large that it will not fit in a float.
A more robust approach is to compute the probability density function as the difference between two consecutive points in the cumulative distribution function, which can be computed using the regularized incomplete beta function (look in SciPy's "special functions" package). Mathematically:
pdf(p, n, k) = cdf(p, n, k) - cdf(p, n, k-1)
Another option is to use the Normal approximation, which is quite accurate for large n. If speed is a concern, this is probably the way to go:
from math import *
def normal_pdf(x, m, v):
return 1.0/sqrt(2*pi*v) * exp(-(x-m)**2/(2*v))
def binomial_pdf(p, n, k):
if n < 100:
return comb(n, k) * p**k * p**(n-k) # Fall back to your current method
return normal_pdf(k, n*p, n*p*(1.0-p))
I haven't tested the code, but that should give you the general idea.
GMPY also supports extended precision floating point calculations. For example:
>>> from gmpy import *
>>>
>>> def f(n,k,p,prec=256):
... return mpf(comb(n,k),prec) * mpf(p,prec)**k * mpf(1-p,prec)**(n-k)
...
>>> print(f(1000,500,0.5))
0.0252250181783608019068416887621024545529410193921696384762532089115753731615931
>>>
I specified a floating point precision of 256 bits. By the way, source forge version is way out of date. The current version is maintained at code.google.com and supports Python 3.x. (Disclaimer: I'm the current maintainer of gmpy.)
casevh
I would look into the GNU Multi-Precision package (gmpy), which allows you to perform arbitrary precision calculations: you could probably do:
comb(n, k, exact=1)/2**k/2**(n-k)
but with the long integers of gmpy.
In fact, if you use exact integer computations, you can easily reach n=10000 for the combinations part; for this, you must use:
comb(n, k, exact=1)
instead of the floating point approximation comb(n, k), which overflows.
However, as the Original Poster noted, the returned (long) integer may be too long to be multiplied by a float!
Furthermore, one quickly runs into another problem: 0.5**1000=9.3…e-302 is already very close to the float underflow…
In summary: if you really need precise results for all k for n~10,000, you need to use a different approach than the formula from the original post, which suffers from the limitations of double precision floating point arithmetics. Using gmpy as indicated above could be a solution (not tested!).
Not specifically a Python solution, but if you can deal with small fractional errors, you might try using Stirling's approximation for n!:
comb(n, k) = n!/(k! * (n-k)!), where n! is approximately sqrt(2*Pin)(n/e)^n for large n.
For n>1000 the fractional errors should be very small.
For the probability calculation with large n, use logarithms for intermediate results:
log p = log(comb(n, k)) - n * log(2)
p = exp(log(p))
# This imports the array function form numpy
from numpy import array
# the following defines the factorial function to be used in the binomial commands/
# n+1 is used in the range to include the nth term
def factorial (n):
f=1
for x in range(1,n+1):
f=f*(x)
return f
# The follwong calculates the binomial coefficients for given values of n & k
def binomial (n,k):
b=1
b=(factorial(n)/(factorial(k)*factorial(n-k)))
return int(b)
# the following lines define the pascal triangle , and print it out for 20 rows./
# in order to include nth term, the n +1 term needs to be in the range. The commands/
# append the next binomial coeficiant to a raw first and then append rows to the triangle/
# and prints a 20 row size pascal triangle
def pascal(T):
triangle=[]
for n in range(T):
r=[]
for k in range(n+1):
r.append(binomial(n,k))
triangle.append(r)
return triangle
for r in pascal(20):
print((r))

Categories

Resources