What is the difference between x**(1/2) , math.sqrt() and cmath.sqrt()?
Why does cmath.sqrt() get complex roots of a quadratic right alone? Should I use that for my square roots exclusively? What do they do in the background differently?
If you look at the documentation for cmath and math respectively, you will find that:
cmath "provides access to mathematical functions for complex numbers"
math "functions cannot be used with complex numbers; use the functions of the same name from the cmath module if you require support for complex numbers."
The (**) operator maps to the pow function, with the important difference that pow converts its arguments to float.
Hence, you may see different results with the three functions for same arguments, as demonstrated here. Please note that if the expression has a real solution, there will be no difference between the value returned by math.sqrt and the real part of the value returned by cmath.sqrt. However, you will get an error with math.sqrt if no real solution is available.
Edit: As #jermenkoo points out, there will be a difference in the value returned by (**) between Python 2 and 3 due to the difference in how the / operator works. However, if you directly use 0.5 instead of 1/2, that should not cause issues.
As an addition to the existing answers, one notable difference is when processing negative numbers:
>>> import math
>>> math.sqrt(-4)
Traceback (most recent call last):
File "<string>", line 301, in runcode
File "<interactive input>", line 1, in <module>
ValueError: math domain error
The sqrt function only works on positive values.
>>> (-4)**0.5
(1.2246467991473532e-16+2j)
The ** operator is able to return a complex number in that case (note the wierd rounding error where the real part should be zero)
import cmath
>>> cmath.sqrt(-4)
2j
cmath.sqrt returns the perfect complex value probably because, as opposed to **, sqrt is a specialized square root computation, not just a float pow function.
** .5 and math.sqrt are going to be nearly identical.
** .5 is going to dispatch you to pow from the standard C library powhttps://hg.python.org/cpython/file/661195a92131/Objects/floatobject.c#l783 and math.sqrt will dispatch you to sqrt in the standard C library sqrt, both of which should have similar performance. A bigger difference would probably be caused by the difference between
from math import sqrt
sqrt(x)
vs
import math
math.sqrt(x)
just because of the lookup of sqrt in the math module.
cmath is different and will be slower. It is for math on complex numbers, which is why it's returning complex numbers. Note that difference between cmath and math is different than packages like cPickle and pickle.
Related
I encountered a problem when I using Sympy to solve problems
Here is my code:
from math import pi, hypot
from sympy import solve, solveset, sqrt, Symbol
one_x=-0.08
one_y=1.28
second_x=0
second_y=0
second_r=7
one_r=7.3
slopes=-16.0000000000 (maybe more trailing 0s)
intercepts=0.0
x=Symbol('x')
solveset(sqrt((x-second_x)**2+(slope*x+intercept-second_y)**2)+second_r-one_r-sqrt((x-one_x)**2+(slope*x+intercept-one_y)**2),x)
That's only part of my code but it raises a lot of errors
but instead, I replaced all of the variables with its value like
x=Symbol('x')
solveset(sqrt((x)**2+((-16)*x)**2)+7-7.3-sqrt((x+0.08)**2+((-16)*x-1.28)**2),x)
It works nicely and i can get an output {-0.0493567429232771}
I think It's because of the type of slopes(-16 compared with -16.000000), I really wanna know why an equation with float number cannot be calculated, and how I can fix it (cause I need it to be more precise so I cannot just ignore the number after the dot )
Thanks so much!
SymPy + algebraic equation + floating point numbers => trouble. Floating point math does not work like normal math, and SymPy is designed for the latter. Small things like 16 (integer) versus 16.0 (float) make a lot of difference in solving equations with SymPy: ideally, you would have no floating point numbers there, creating exact rational numbers instead, like this.
from sympy import S
one_x = S('-0.08')
However, you have floating point data and are looking for a floating point solution. This makes SymPy the wrong tool for the job. SymPy is for doing math with symbols, not for crunching floating point numbers. The correct solution is to use an appropriate solve from SciPy, such as brentq. It takes a bracketing interval as an input (where the function has different signs at both ends). For example:
from scipy.optimize import brentq
eq = lambda x: np.sqrt((x-second_x)**2 + (slope*x+intercept-second_y)**2) + second_r - one_r - np.sqrt((x-one_x)**2 + (slope*x + intercept - one_y)**2)
brentq(eq, -10, 10) # returns -0.049356742923277075
If you stick with SymPy, that means your equation is going outsourced to mpmath library, which is much more limited in the numerical root finding and optimization. To get a solution to converge with its methods, you'll need a really good starting point: apparently, one_x/2 is such a point.
from sympy import sqrt, Symbol, nsolve
# ... as in your code
nsolve(sqrt((x-second_x)**2+(slope*x+intercept-second_y)**2)+second_r-one_r-sqrt((x-one_x)**2+(slope*x+intercept-one_y)**2), one_x/2)
returns -0.0493567429232771.
By using sympy.solveset, which is intended for symbolic solution, you deprive yourself not only of SciPy's powerful numeric solvers, but also of an opportunity to set a good starting value for the numeric search which sympy.nsolve provides. Hence the lack of convergence in this numerically tricky problem. By the way, this is what makes it numerically tricky: the function is nearly constant most of the time, with one rapid change.
I've tried to solve the problem myself but i cant. Its a function in order to solve 2nd grade equations when y=0 like 'ax2+bx+c=0'. when i execute it it says me there is math domain error. if u can help me it will be nice thx.
a=raw_input('put a number for variable a:')
b=raw_input('put a number for variable b:')
c=raw_input('put a number for variable c:')
a=float(a)
b=float(b)
c=float(c)`
import math
x=(-b+math.sqrt((b**2)-4*a*c))/2*a
print x`
x=(-b-math.sqrt((b**2)-4*a*c))/2*a`
print x
PD:im starting with python so im quite a disaster sorry.
The issue here is that the standard math library in python cannot handle complex variables. The sqrt you've got up there reflects this.
If you want to handle a function that could have complex variables (such as the one above) I would suggest using the cmath library, which has a replacement cmath.sqrt function.
You could change your above code to the following:
from cmath import sqrt
a = raw_input('put a number for variable a:')
b = raw_input('put a number for variable b:')
c = raw_input('put a number for variable c:')
a = float(a)
b = float(b)
c = float(c)`
x = (-b + sqrt((b**2) - 4 * a * c)) / 2 * a
print x`
x = (-b - sqrt((b**2) - 4 * a * c)) / 2 * a`
print x
and it should fix your problem (I also made some edits to make the code look a little more pythonic (read: pep8 compliant))
First, it's worth noting that in "2nd grade math", that equation doesn't have a solution with the values you (presumably) entered.* When you get to high school math and learn about imaginary numbers, you learn that all quadratic equations actually do have solutions, it's just that sometimes the solutions are complex numbers. And then, when you get to university, you learn that whether or not the equations have solutions depends on the domain; the function to real numbers and the function to complex numbers are different functions. So, from either a 2nd-grade perspective or a university perspective, Python is doing the right thing by raising a "math domain error".
* Actually, do you even learn about quadratic equations before middle school? That seems a bit early…
The math docs explain:
These functions cannot be used with complex numbers; use the functions of the same name from the cmath module if you require support for complex numbers. The distinction between functions which support complex numbers and those which don’t is made since most users do not want to learn quite as much mathematics as required to understand complex numbers. Receiving an exception instead of a complex result allows earlier detection of the unexpected complex number used as a parameter, so that the programmer can determine how and why it was generated in the first place.
But there's another reason for this: math was specifically designed to be thin wrappers around the standard C library math functions. It's part of the intended goal that you can take code written for another language that uses C's <math.h>, C++'s <cmath>, or similar functions in Perl, PHP, etc. and have it work the same way with the math module in Python.
So, if you want the complex roots, all you have to do is import cmath and use cmath.sqrt instead of math.sqrt.
As a side note: In general, the operators and other builtins are more "friendly" than the functions from these modules. However, until 3.0, the ** operator breaks this rule, so ** .5 will just raise ValueError: negative number cannot be raised to a fractional power. If you upgrade to 3.x, it will work as desired. (This change is exactly like the one with integer division giving a floating-point result, but there's no __future__ statement to enable it in 2.6-2.7 because it was deemed to be less of a visible and important change.)
I am working on a python program to calculate numbers in the Fibonacci sequence. Here is my code:
import math
def F(n):
return ((1+math.sqrt(5))**n-(1-math.sqrt(5))**n)/(2**n*math.sqrt(5))
def fib(n):
for i in range(n):
print F(i)
My code uses this formula for finding the Nth number in the Fibonacci sequence:
This can calculate many of the the numbers in the Fibonacci sequence but I do get overflow errors.
How can I improve this code and prevent overflow errors?
Note: I am using python 2.7.
Python's integers are arbitrary precision so if you calculate the Fibonacci sequence using an interative algorithm, you can compute exact results.
>>> def fib(n):
... a = 0
... b = 1
... while n > 0:
... a, b = b, a + b
... n = n - 1
... return a
...
>>> fib(100)
354224848179261915075L
There are several multiple precision floating-point libraries available for Python. The decimal module is included with Python and was originally intended for financial calculations. It does support sqrt() so you can do the following:
>>> import decimal
>>> decimal.setcontext(decimal.Context(prec=40))
>>> a=decimal.Decimal(5).sqrt()
>>> a
Decimal('2.236067977499789696409173668731276235441')
>>> ((1+a)**100 - (1-a)**100)/(a*(2**100))
Decimal('354224848179261915075.0000000000000000041')
Other libraries are mpmath and gmpy2.
>>> import gmpy2
>>> gmpy2.set_context(gmpy2.context(precision=150))
>>> a=gmpy2.sqrt(5)
>>> a
mpfr('2.2360679774997896964091736687312762354406183598',150)
>>> ((1+a)**100 - (1-a)**100)/(a*(2**100))
mpfr('354224848179261915075.00000000000000000000000248',150)
>>> gmpy2.fib(100)
mpz(354224848179261915075L)
gmpy2 can also computer Fibonacci numbers directly (as shown above).
Disclaimer: I maintain gmpy2.
I don't know if this is acceptable to you, but you could just use integer arithmetic as calculate the fib number using the recurrence relation (e.g., F3 = F2 + F1).
Since Python 2.5?, you can do arbitrary precision integer arithmetic -- pretty much eliminate overflow problems -- If you try to calculate F(10000) it will doubtless get very slow.
Also, check out the decimal module -- IIRC correctly, you can use in with Python 2.7, you can specify the precision of the decimal arithmetic -- This would allow you to continue using same algorithm -- except for using the decimal type.
ADDED
You can easily overlook that the decimal class includes a square root method. You would need to use this method instead of math.sqrt() since you will need to retain the full precision of the decimal class.
Also sqrt(5) is a relatively expensive operation. Only calculate it one time
Your statement of How can I improve this code... is kind of vague, so I will take it to mean shortening your code:
import math
def fib(j):
for i in [int(((1+math.sqrt(5))**n-(1-math.sqrt(5))**n)/(2**n*math.sqrt(5))) for n in range(j)]: print i
You can combine both of your functions to make just one function, and using list comprehension, you can make that function run in one line.
You cannot prevent overflow errors if you are working with very large numbers, instead, try catching them and then breaking:
import math
def fib(j):
try:
for i in [int(((1+math.sqrt(5))**n-(1-math.sqrt(5))**n)/(2**n*math.sqrt(5))) for n in range(j)]: print i
except Exception as e:
print 'There was an error, your number was too large!'
The second one will first loop over everything and make sure there is no error, and if there isn't, it will proceed to print it.
In the code below: highly simplified. I get ZeroDivisionError: float division
Any value below one gives errors. Other times 5/365 gives the error.
How do I fix?
import math
def top( t):
return ((.3 / 2) * t) / (.3 * math.sqrt(t))
t = 365/365
top= top(t)
print (top)
The problem is here:
t = 365/365
You are dividing two integers, so python is using integer division. In integer division, the quotient is rounded down. For example, 364/365 would be equal to 0. (365/365 works because it is equal to 1, which is still 1 rounded down.)
Instead, use float division, like so.
t = 365.0/365.0
In addition to cheeken's answer, you can put the following at the top of your modules:
from __future__ import division
Doing so will make the division operator work the way you want it to i.e always perform a (close approximation of) true mathematical division. The default behaviour of the division operator (where it performs truncating integer division if the arguments happen to be bound to integers) was inherited from C, but it was eventually realised that it was not a great fit for a dynamically typed language like Python. In Python 3, this no longer happens.
In my Python 2 modules, I almost always import division from __future__, so that I can't get caught out by accidentally passing integers to a division operation I don't expect to truncate.
It's worth noting that from __future__ import ... statements have to be the very first thing in your module (I think you can have comments and a docstring before it, nothing else). It's not really a normal import statement, even though it looks like one; it actually changes the way the Python interpreter reads your code, so it can't wait until runtime to be exectuted like a normal import statement. Also remember that import __future__ does not have any of the magic effects of from __future__ import ....
Try this:
exponent = math.exp(-(math.pow(x-mean,2)/(2*math.pow(stdev,2))))
A ZeroDivisionError is encountered when you try to divide by zero.
Why is python telling me "TypeError: pow expected 2 arguments, got 3" despite it working in IDLE (sometimes it tells me that in IDLE as well)? im simply doing pow(a,b,c). my program is very short and i do not change the definition of pow at any time since i need to use it for some exponentiation.
NOTE: This is the pow from __builtin__, not Math
Built-in pow takes two or three arguments. If you do from math import * then it is replaced by math's pow, which takes only two arguments. My recommendation is to do import math, or explicitly list functions you use in import list. Similar issue happens with open vs. os.open.
If you are using math functions a lot and the three parameter version of pow infrequently a way around this in python 2.7 is to import __builtin__ and call __builtin__.pow for the 3 paramete
http://docs.python.org/release/2.6.5/library/functions.html
pow(x, y[, z]) Return x to the power
y; if z is present, return x to the
power y, modulo z (computed more
efficiently than pow(x, y) % z). The
two-argument form pow(x, y) is
equivalent to using the power
operator: x**y.
The arguments must have numeric types.
With mixed operand types, the coercion
rules for binary arithmetic operators
apply. For int and long int operands,
the result has the same type as the
operands (after coercion) unless the
second argument is negative; in that
case, all arguments are converted to
float and a float result is delivered.
For example, 102 returns 100, but
10-2 returns 0.01. (This last
feature was added in Python 2.2. In
Python 2.1 and before, if both
arguments were of integer types and
the second argument was negative, an
exception was raised.) If the second
argument is negative, the third
argument must be omitted. If z is
present, x and y must be of integer
types, and y must be non-negative.
(This restriction was added in Python
2.2. In Python 2.1 and before, floating 3-argument pow() returned
platform-dependent results depending
on floating-point rounding accidents.)
Perhaps you're violating the bold portion?