How to check if complex number is a whole number - python

Given a value numerical value x, you can just do this float(x).is_integer() to check if it's an integer. Is there a way to do this for complex numbers?
I'm trying to use list comprehension to take only the integer roots of a polynomial over a finite field which are integers.
[r for r in solve(f,domain=FiniteField(p)) if float(r).is_integer()]
but if the solve function returns complex roots, this doesn't work.
Does anyone know how to either: check if a given (possibly complex number) is an integer OR know if there's a SymPy function to get the roots of a polynomial over a finite field which are integers?

Use the ground_roots function along with the modulus keyword argument. This returns the roots modulo p, with multiplicities. Here's an example:
>>> from sympy import Symbol, ground_roots
>>> x = Symbol('x')
>>> f = x**5 + 7*x + 1
>>> p = 13
>>> ground_roots(f, modulus=p)
{-5: 1, 4: 2}
That says that the roots of poly modulo 13 are -5 and 4, with the root 4 having multiplicity 2.
By the way, it looks to me as though complex numbers are a red herring here: the roots of an integral polynomial over a finite field can't naturally be regarded as complex numbers. The call to solve in your original post is ignoring the domain argument and is simply giving algebraic numbers (which can reasonably be interpreted as complex numbers) as its results, which is probably why you ended up looking at complex numbers. But these aren't going to help when trying to find the roots modulo a prime p.

float.is_integer(z.real) tells you if the real part is integer

If you want to check if imaginary part is zero, you can do this:
In [17]: a=2 + 2j
In [18]: bool(a.imag)
Out[18]: True
In [19]: b=2 + 0j
In [20]: bool(b.imag)
Out[20]: False

Using a list comprehension as in your original question, one could do:
roots = [complex(r) for r in solve(f, domain=FiniteField(p))]
int_roots = [z.real for z in roots if z.real.is_integer() and not z.imag]

Related

Exact value of a root on Python

I'm writing a programme that converts complex numbers.
Right now I'm having problems with this piece of code:
import numpy
complexnr = 1+1j
mod= numpy.absolute(complexnr)
print(mod)
The output of this code is:
1.4142135623730951
I would like to get √2 as the output.
I have been advised to use the sympy module but I have had no luck with this either. What would be the easiest way to get this result?
EDIT
input_list = ["Enter your complex number (a+bi): ", \
"Degrees or radians?", \
"To how many decimal places do you want to round the argument?"]
output = multenterbox(text, title, input_list)
algebraline = output[0]
choice = output[1]
round2 = int(output[2])
#converting complex number to a suitable form for numpy
if "i" in algebraline:
j = algebraline.replace("i","j")
indeks = algebraline.index("i")
list = []
for element in algebraline:
list.append(element)
if "i" in algebraline and algebraline[indeks-1]=="+" or algebraline[indeks-1]=="-":
list.insert(indeks, 1)
x = "".join(str(e) for e in list)
j = x.replace("i","j")
arv = eval(j)
elif "i" not in algebraline:
arv = eval(algebraline)
#let's find the module
a = int(list[0])
b = int(list[2])
module = sqrt(a**2+b**2)
this method works well when the complex number is 1+i for example, however when i try to insert sqrt(3)-1i, the list looks like this ['s', 'q', 'r', 't', '(', '3', ')', '-', 1, 'i'] and my programme won't work. Same problem occurs when b is a root (for example 1-sqrt(3)i). What can be done to make it work for square roots as well? (I need numpy later on to calculate angles, that's why converting 'i' into 'j' is important)
Works by using
I (from sympy) rather than 1j
builtin abs function which calls sympby.Abs for complex arguments
Code
from sympy import I
complexnr = 1 + I # use I rather than 1j
display(abs(complexnr)) # also works with np.abs and np.absolute
Output:
print(abs(complexnr))
Output: sqrt(2)
If you want to use SymPy, you have to write the complex numbers as sympy expressions.
from sympy import *
cabs = lambda z: sqrt(re(z)**2 + im(z)**2)
complexnr = 1 + 1j
print(cabs(complexnr))
# out: 1.4142135623731
We are getting a float number because complexnr is of type complex and its real and imaginary parts are of type float. Thus, SymPy's re and im functions returns float numbers. But when sqrt receives a float number, it evaluates the result.
We can workaround this problem in two ways.
The first: if we are dealing with simple complex numbers where real and imaginary parts are integers, we can write the complex number as a string, sympify it (which means convert to a sympy expression):
complexnr = sympify("1 + 1j")
print(cabs(complexnr))
# out: sqrt(2)
A second way consist in using the complex number directly, then apply nsimplify in order to attempt to convert the resulting float number to some symbolic form:
complexnr = 1 + 1j
result = cabs(complexnr) # result is a Float number, 1.4142135623731
print(result.nsimplify())
# out: sqrt(2)

How do I calculate square root in Python?

I need to calculate the square root of some numbers, for example √9 = 3 and √2 = 1.4142. How can I do it in Python?
The inputs will probably be all positive integers, and relatively small (say less than a billion), but just in case they're not, is there anything that might break?
Related
Integer square root in python
How to find integer nth roots?
Is there a short-hand for nth root of x in Python?
Difference between **(1/2), math.sqrt and cmath.sqrt?
Why is math.sqrt() incorrect for large numbers?
Python sqrt limit for very large numbers?
Which is faster in Python: x**.5 or math.sqrt(x)?
Why does Python give the "wrong" answer for square root? (specific to Python 2)
calculating n-th roots using Python 3's decimal module
How can I take the square root of -1 using python? (focused on NumPy)
Arbitrary precision of square roots
Note: This is an attempt at a canonical question after a discussion on Meta about an existing question with the same title.
Option 1: math.sqrt()
The math module from the standard library has a sqrt function to calculate the square root of a number. It takes any type that can be converted to float (which includes int) as an argument and returns a float.
>>> import math
>>> math.sqrt(9)
3.0
Option 2: Fractional exponent
The power operator (**) or the built-in pow() function can also be used to calculate a square root. Mathematically speaking, the square root of a equals a to the power of 1/2.
The power operator requires numeric types and matches the conversion rules for binary arithmetic operators, so in this case it will return either a float or a complex number.
>>> 9 ** (1/2)
3.0
>>> 9 ** .5 # Same thing
3.0
>>> 2 ** .5
1.4142135623730951
(Note: in Python 2, 1/2 is truncated to 0, so you have to force floating point arithmetic with 1.0/2 or similar. See Why does Python give the "wrong" answer for square root?)
This method can be generalized to nth root, though fractions that can't be exactly represented as a float (like 1/3 or any denominator that's not a power of 2) may cause some inaccuracy:
>>> 8 ** (1/3)
2.0
>>> 125 ** (1/3)
4.999999999999999
Edge cases
Negative and complex
Exponentiation works with negative numbers and complex numbers, though the results have some slight inaccuracy:
>>> (-25) ** .5 # Should be 5j
(3.061616997868383e-16+5j)
>>> 8j ** .5 # Should be 2+2j
(2.0000000000000004+2j)
Note the parentheses on -25! Otherwise it's parsed as -(25**.5) because exponentiation is more tightly binding than unary negation.
Meanwhile, math is only built for floats, so for x<0, math.sqrt(x) will raise ValueError: math domain error and for complex x, it'll raise TypeError: can't convert complex to float. Instead, you can use cmath.sqrt(x), which is more more accurate than exponentiation (and will likely be faster too):
>>> import cmath
>>> cmath.sqrt(-25)
5j
>>> cmath.sqrt(8j)
(2+2j)
Precision
Both options involve an implicit conversion to float, so floating point precision is a factor. For example:
>>> n = 10**30
>>> x = n**2
>>> root = x**.5
>>> n == root
False
>>> n - root # how far off are they?
0.0
>>> int(root) - n # how far off is the float from the int?
19884624838656
Very large numbers might not even fit in a float and you'll get OverflowError: int too large to convert to float. See Python sqrt limit for very large numbers?
Other types
Let's look at Decimal for example:
Exponentiation fails unless the exponent is also Decimal:
>>> decimal.Decimal('9') ** .5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ** or pow(): 'decimal.Decimal' and 'float'
>>> decimal.Decimal('9') ** decimal.Decimal('.5')
Decimal('3.000000000000000000000000000')
Meanwhile, math and cmath will silently convert their arguments to float and complex respectively, which could mean loss of precision.
decimal also has its own .sqrt(). See also calculating n-th roots using Python 3's decimal module
SymPy
Depending on your goal, it might be a good idea to delay the calculation of square roots for as long as possible. SymPy might help.
SymPy is a Python library for symbolic mathematics.
import sympy
sympy.sqrt(2)
# => sqrt(2)
This doesn't seem very useful at first.
But sympy can give more information than floats or Decimals:
sympy.sqrt(8) / sympy.sqrt(27)
# => 2*sqrt(6)/9
Also, no precision is lost. (√2)² is still an integer:
s = sympy.sqrt(2)
s**2
# => 2
type(s**2)
#=> <class 'sympy.core.numbers.Integer'>
In comparison, floats and Decimals would return a number which is very close to 2 but not equal to 2:
(2**0.5)**2
# => 2.0000000000000004
from decimal import Decimal
(Decimal('2')**Decimal('0.5'))**Decimal('2')
# => Decimal('1.999999999999999999999999999')
Sympy also understands more complex examples like the Gaussian integral:
from sympy import Symbol, integrate, pi, sqrt, exp, oo
x = Symbol('x')
integrate(exp(-x**2), (x, -oo, oo))
# => sqrt(pi)
integrate(exp(-x**2), (x, -oo, oo)) == sqrt(pi)
# => True
Finally, if a decimal representation is desired, it's possible to ask for more digits than will ever be needed:
sympy.N(sympy.sqrt(2), 1_000_000)
# => 1.4142135623730950488016...........2044193016904841204
NumPy
>>> import numpy as np
>>> np.sqrt(25)
5.0
>>> np.sqrt([2, 3, 4])
array([1.41421356, 1.73205081, 2. ])
docs
Negative
For negative reals, it'll return nan, so np.emath.sqrt() is available for that case.
>>> a = np.array([4, -1, np.inf])
>>> np.sqrt(a)
<stdin>:1: RuntimeWarning: invalid value encountered in sqrt
array([ 2., nan, inf])
>>> np.emath.sqrt(a)
array([ 2.+0.j, 0.+1.j, inf+0.j])
Another option, of course, is to convert to complex first:
>>> a = a.astype(complex)
>>> np.sqrt(a)
array([ 2.+0.j, 0.+1.j, inf+0.j])
Newton's method
Most simple and accurate way to compute square root is Newton's method.
You have a number which you want to compute its square root (num) and you have a guess of its square root (estimate). Estimate can be any number bigger than 0, but a number that makes sense shortens the recursive call depth significantly.
new_estimate = (estimate + num/estimate) / 2
This line computes a more accurate estimate with those 2 parameters. You can pass new_estimate value to the function and compute another new_estimate which is more accurate than the previous one or you can make a recursive function definition like this.
def newtons_method(num, estimate):
# Computing a new_estimate
new_estimate = (estimate + num/estimate) / 2
print(new_estimate)
# Base Case: Comparing our estimate with built-in functions value
if new_estimate == math.sqrt(num):
return True
else:
return newtons_method(num, new_estimate)
For example we need to find 30's square root. We know that the result is between 5 and 6.
newtons_method(30,5)
number is 30 and estimate is 5. The result from each recursive calls are:
5.5
5.477272727272727
5.4772255752546215
5.477225575051661
The last result is the most accurate computation of the square root of number. It is the same value as the built-in function math.sqrt().
This answer was originally posted by gunesevitan, but is now deleted.
Python's fractions module and its class, Fraction, implement arithmetic with rational numbers. The Fraction class doesn't implement a square root operation, because most square roots are irrational numbers. However, it can be used to approximate a square root with arbitrary accuracy, because a Fraction's numerator and denominator are arbitrary-precision integers.
The following method takes a positive number x and a number of iterations, and returns upper and lower bounds for the square root of x.
from fractions import Fraction
def sqrt(x, n):
x = x if isinstance(x, Fraction) else Fraction(x)
upper = x + 1
for i in range(0, n):
upper = (upper + x/upper) / 2
lower = x / upper
if lower > upper:
raise ValueError("Sanity check failed")
return (lower, upper)
See the reference below for details on this operation's implementation. It also shows how to implement other operations with upper and lower bounds (although there is apparently at least one error with the log operation there).
Daumas, M., Lester, D., Muñoz, C., "Verified Real Number Calculations: A Library for Interval Arithmetic", arXiv:0708.3721 [cs.MS], 2007.
Alternatively, using Python's math.isqrt, we can calculate a square root to arbitrary precision:
Square root of i within 1/2n of the correct value, where i is an integer:Fraction(math.isqrt(i * 2**(n*2)), 2**n).
Square root of i within 1/10n of the correct value, where i is an integer:Fraction(math.isqrt(i * 10**(n*2)), 10**n).
Square root of x within 1/2n of the correct value, where x is a multiple of 1/2n:Fraction(math.isqrt(x * 2**(n)), 2**n).
Square root of x within 1/10n of the correct value, where x is a multiple of 1/10n:Fraction(math.isqrt(x * 10**(n)), 10**n).
In the foregoing, i or x must be 0 or greater.
Binary search
Disclaimer: this is for a more specialised use-case. This method might not be practical in all circumstances.
Benefits:
can find integer values (i.e. which integer is the root?)
no need to convert to float, so better precision (can be done that well too)
I personally implemented this one for a crypto CTF challenge (RSA cube root attack),where I needed a precise integer value.
The general idea can be extended to any other root.
def int_squareroot(d: int) -> tuple[int, bool]:
"""Try calculating integer squareroot and return if it's exact"""
left, right = 1, (d+1)//2
while left<right-1:
x = (left+right)//2
if x**2 > d:
left, right = left, x
else:
left, right = x, right
return left, left**2==d
EDIT:
As #wjandrea have also pointed out, **this example code can NOT compute **. This is a side-effect of the fact that it does not convert anything into floats, so no precision is lost. If the root is an integer, you get that back. If it's not, you get the biggest number whose square is smaller than your number. I updated the code so that it also returns a bool indicating if the value is correct or not, and also fixed an issue causing it to loop infinitely (also pointed out by #wjandrea). This implementation of the general method still works kindof weird for smaller numbers, but above 10 I had no problems with.
Overcoming the issues and limits of this method/implementation:
For smaller numbers, you can just use all the other methods from other answers. They generally use floats, which might be a loss of precision, but for small integers that should mean no problem at all. All of those methods that use floats have the same (or nearly the same) limit from this.
If you still want to use this method and get float results, it should be trivial to convert this to use floats too. Note that that will reintroduce precision loss, this method's unique benefit over the others, and in that case you can also just use any of the other answers. I think the newton's method version converges a bit faster, but I'm not sure.
For larger numbers, where loss of precision with floats come into play, this method can give results closer to the actual answer (depending on how big is the input). If you want to work with non-integers in this range, you can use other types, for example fixed precision numbers in this method too.
Edit 2, on other answers:
Currently, and afaik, the only other answer that has similar or better precision for large numbers than this implementation is the one that suggest SymPy, by Eric Duminil. That version is also easier to use, and work for any kind of number, the only downside is that it requires SymPy. My implementation is free from any huge dependencies if that is what you are looking for.
Arbitrary precision square root
This variation uses string manipulations to convert a string which represents a decimal floating-point number to an int, calls math.isqrt to do the actual square root extraction, and then formats the result as a decimal string. math.isqrt rounds down, so all produced digits are correct.
The input string, num, must use plain float format: 'e' notation is not supported. The num string can be a plain integer, and leading zeroes are ignored.
The digits argument specifies the number of decimal places in the result string, i.e., the number of digits after the decimal point.
from math import isqrt
def str_sqrt(num, digits):
""" Arbitrary precision square root
num arg must be a string
Return a string with `digits` after
the decimal point
Written by PM 2Ring 2022.01.26
"""
int_part , _, frac_part = num.partition('.')
num = int_part + frac_part
# Determine the required precision
width = 2 * digits - len(frac_part)
# Truncate or pad with zeroes
num = num[:width] if width < 0 else num + '0' * width
s = str(isqrt(int(num)))
if digits:
# Pad, if necessary
s = '0' * (1 + digits - len(s)) + s
s = f"{s[:-digits]}.{s[-digits:]}"
return s
Test
print(str_sqrt("2.0", 30))
Output
1.414213562373095048801688724209
For small numbers of digits, it's faster to use decimal.Decimal.sqrt. Around 32 digits or so, str_sqrt is roughly the same speed as Decimal.sqrt. But at 128 digits, str_sqrt is 2.2× faster than Decimal.sqrt, at 512 digits, it's 4.3× faster, at 8192 digits, it's 7.4× faster.
Here's a live version running on the SageMathCell server.
find square-root of a number
while True:
num = int(input("Enter a number:\n>>"))
for i in range(2, num):
if num % i == 0:
if i*i == num:
print("Square root of", num, "==>", i)
break
else:
kd = (num**0.5) # (num**(1/2))
print("Square root of", num, "==>", kd)
OUTPUT:-
Enter a number: 24
Square root of 24 ==> 4.898979485566356
Enter a number: 36
Square root of 36 ==> 6
Enter a number: 49
Square root of 49 ==> 7
✔ Output 💡 CLICK BELOW & SEE ✔

Python innacuracies with large numbers?

I have to write a function that uses another function, but the other function has to return integers which get fairly innacurate with large numbers.
My code:
import math
def reduce(n, d):
m = min(n, d)
for i in range(m, 1, -1):
if n%i==0 and d%i==0:
n = n//i
d = d//i
return (n, d)
def almost_square(n, d):
f = n/d
c = math.ceil(f)
n*=c
return reduce(n, d)
def destiny(n, d):
b = n/d
fraction = n, d
while not b.is_integer():
breuk = almost_square(fraction[0], fraction[1])
b = fraction[0]/fraction[1]
return int(b)
What the functions are supposed to do:
reduce: just simplifying the fraction, so 2/4 becomes 1/2 for example
almost_square: multiplying the fraction with the rounded up integer of the fraction
destiny: applying almost square on a fraction until it returns an integer.
The thing is, my uni works with a program that tries 50 test cases for each function and you only completed the exercise when every function works for all 50 test cases, and they expect the function 'reduce' to return a tuple of integers, but making integers of the numbers there makes my function 'destiny' innacurate, or at least I think so.
So out of the 50 test cases, all 50 work on the function reduce, all 50 work on the function almost_square, but 5 fail for the function destiny which are:
destiny(10, 6), my output: 1484710602474311424, expected output: 1484710602474311520
destiny(17, 13), my output: 59832260230817688435680083968, expected output: 59832260230817687634146563200
destiny(10, 3), my output: 1484710602474311424, expected output: 1484710602474311520
destiny(15, 9), my output: 1484710602474311424, expected output: 1484710602474311520
destiny(11, 5), my output: 494764640798827343035498496, expected output: 494764640798827359861461484
Anything that could fix this?
There is some floating point arithmetic in that code, which can slightly throw off the results, and apparently it did. Forget about float, don't use any "floats, but larger" libraries either, integer arithmetic is the way to go.
For example,
f = n/d
c = math.ceil(f)
n*=c
This code looks like it computes n * ⌈n / d⌉, but it only approximately computes that because it uses floating point arithmetic, requiring values to be rounded to the nearest float (for example, int(float(1484710602474311520)) is 1484710602474311424). It should be implemented using integer arithmetic, for example like this:
n *= (n + d - 1) // d
The destiny function should not use floating point division either, and it does not need to. The "is b an integer" test can be stated equivalently as "does d divide n", which can be implemented with integer arithmetic.
Also for that reduce function you can use math.gcd, or implement gcd yourself, the implementation that you have now is very slow.
With those changes, I get the right results for the test cases that you mentioned. I could show the code, but since it is an assignment, you should probably write the code yourself. Asking this question at all is already risky.
Integers don't get inaccurate with large numbers. Floating point numbers do. And you are using floating point numbers.
Rewrite your algorithm to only use integers.

subs() for large number of variables

I am working on optimization, and I want to code a functions where I can sub() larger number of variables.
for this, I generated a m functions with n variables. For example, let say 3 functions and 2 variables.
num_var=2
x=symbols('x0:num_var')
I generated this functions:
f=[5*x0 + 4*x1 + 6, -4*x0 - 5*x1 - 6, -8*x0 - 10]
and I have a point like:
point=[-2.8,1.74]
If I want to sub() in each function, what is the fastest way to do this?
f[0].subs([(x[0],point[0]),(x[1],point[1])])
(this will give evaluation of first function in point)
And I get three function evaluations in list:
fun_eval=[some number,some number, ... (in size of number of functions)]
The question is how can I write a code to do evaluations for larger number of variables in large number of functions?
>>> from sympy import *
>>> x0, x1 = x = symbols('x:2')
>>> f = [5*x0+4*x1+6, -4*x0-5*x1-6, -8*x0-10]
>>> point = (-2.8, 1.74)
>>> [fi.subs(zip(x, point)) for fi in f]
[-1.04000000000000, -3.50000000000000, 12.4000000000000]
See http://docs.sympy.org/latest/tutorial/basic_operations.html#lambdify. If you want to efficiently evaluate a function at a large number of points, you should use lambdify.
>>> func = lambdify(x, f)
>>> func(*point)
[-1.04, -3.5, 12.399999999999999]
By default, it uses subs, but if you have numpy installed, you can use it for much faster evaluation, by passing module="numpy" to lambdify.
By the way, your symbols('x0:num_var') does not actually use the num_var variable. You need to use symbols('x0:%d' % num_var).

number approximation in python

I have a list of floating points numbers which represent x and y coordinates of points.
(-379.99418604651157, 47.517234218543351, 0.0) #representing point x
an edge contains two such numbers.
I'd like to use a graph traversal algorithm, such as dijkstra, but using floating point numbers such as the ones above don't help.
What I'm actually looking for is a way of approximating those numbers:
(-37*.*, 4*.*, 0.0)
is there a python function that does that?
"...using floating point numbers such as the ones above don't help..." - why not? I don't recall integers as a requirement for Dijkstra. Aren't you concerned with the length of the edge? That's more likely to be a floating point number, even if the endpoints are expressed in integer values.
I'm quoting from Steve Skiena's "Algorithm Design Manual":
Dijkstra's algorithm proceeds in a
series of rounds, where each round
establishes the shortest path from s
to some new vertex. Specifically, x
is the vertex that minimizes dist(s,
vi) + w(vi, x) over all unfinished 1
<= i <= n...
Distance - no mention of integer.
Like so?
>>> x, y, z = (-379.99418604651157, 47.517234218543351, 0.0)
>>> abs(x - -370) < 10
True
>>> abs(y - 40) < 10
True
Given your vector
(-379.99418604651157, 47.517234218543351, 0.0) #representing point x
The easiest way to perform rounding that works like you would expect would probably be to use the decimal module: http://docs.python.org/library/decimal.html .
from decimal import Decimal:
point = (-379.99418604651157, 47.517234218543351, 0.0) #representing point x
converted = [Decimal(str(x)) for x in point]
Then, to get an approximation, you can use the quantize method:
>>> converted[0].quantize(Decimal('.0001'), rounding="ROUND_DOWN")
Decimal("-379.9941")
This approach has the advantage of the built in ability to avoid rounding errors. Hopefully this is helpful.
Edit:
After seeing your comment, it looks like you're trying to see if two points are close to each other. These functions might do what you want:
def roundable(a,b):
"""Returns true if a can be rounded to b at any precision"""
a = Decimal(str(a))
b = Decimal(str(b))
return a.quantize(b) == b
def close(point_1, point_2):
for a,b in zip(point_1, point_2):
if not (roundable(a,b) or roundable(b,a)):
return False
return True
I don't know if this is better than an epsilon approach, but it's fairly simple to implement.
I'm not sure what the problem is with the floating point numbers, but there are several ways you can approximate your values. If you just want to round them you can use math.ceil(), math.floor() and math.trunc().
If you actually want to keep track of the precision, there are a bunch of multi-precision math libraries listed on the wiki which might be useful.
I suppose that you want to approximate the number so that you can visually easily understand you're algorithm while stepping into it (as Djikstra pose no limitation on the coordinate of the node, in fact it is only interested with the cost of edges).
A simple function to approximate numbers:
>>> import math
>>> def approximate(value, places = 0):
... factor = 10. ** places
... return factor * math.trunc(value / factor)
>>> p = (-379.99418604651157, 47.517234218543351, 0.0)
>>> print [ approximate(x, 1) for x in p ]
[-370.0, 40.0, 0.0]

Categories