I have written the following code to find the area of triangle in terms of its three sides a, b and c:
s = lambda a, b, c : (a + b + c)/2
area_tri = lambda a, b, c : (s(a,b,c) * (s(a,b,c)-a) * (s(a,b,c)-b) * \
(s(a,b,c)-c)) ** 0.5
area_tri(1, 2, 3)
Output: 7.3484692283495345
I have two questions. First, how to reduce the repeated typing of s(a,b,c) in the lambda function for area_tri? Secondly, conjoined to the first question, how to reduce the number of invocations to lambda s in area_tri?
There is a way:
area_tri = lambda a, b, c: (lambda x=s(a,b,c): (x * (x-a) * (x-b) * (x*c)) ** 0.5)()
Without a lambda but in one line it can be a bit shorter:
def area_tri(a, b, c): x = s(a,b,c); return (x * (x-a) * (x-b) * (x*c)) ** 0.5
However unless you're golfing, this should be properly formatted:
def area_tri(a, b, c):
x = s(a,b,c)
return (x * (x-a) * (x-b) * (x*c)) ** 0.5
Related
I'm trying to understand how complex numbers get multiplied. when I multiply two numbers it always seems to give me an arbitrary amount. for example,
complex(10,9)*complex(11,13) equals complex(-7,229)and complex(10,1)*complex(10,2) equals complex(98,30). is there a mathematical way to figure out 2 complex numbers multiplied and if so, what is is it?
The result is not arbitrary, it is following the definition of complex multiplication:
For example if you have
x = a + j * b
y = c + j * d
then the expression for multiplication is
x * y = (a * c - b * d) + j (a * d + b * c)
For your example complex(10,9) * complex(11,13) that would evaluate to
(10 * 11 - 9 * 13) + j * (10 * 13 + 9 * 11)
(-7 + 229j)
which is exactly what Python shows
>>> complex(10,9) * complex(11,13)
(-7+229j)
Complex number multiplication operates in this way:
(a + ib) * (c + id) = a * c + a * id + ib * c + ib * id
= a * c - b * d + i(a * d + b * c)
So, in Python, the result is like this:
complex(a, b) * complex(c, d) = complex(a * c - b * d, a * d + b * c)
Example:
complex(10, 9) * complex(11, 13) = complex(10 * 11 - 9 * 13, 10 * 13 + 9 * 11)
= complex(-7, 227)
If you have 2 complex numbers, the first a + bj, and the second c + dj, then the product (a + bj) * (c + dj) = a*c - b*d + (a*d + b*c)j. The way to think about it is that j is equal to the square root of -1, so j*j = -1, and then just multiply out the brackets as normal. See below:
a, b = 10, 9
c, d = 11, 13
print(complex(a, b)*complex(c, d))
print(a*c - b*d, a*d + b*c)
Output:
(-7+229j)
-7 229
Another way to understand complex number multiplication is geometrically. We can think of complex numbers as two dimensional vectors, things with a length and direction. Then when multiplying a complex number with length r and direction a by another with length s and direction b, you get a complex number with length r*s and direction a+b, i.e. a complex number with length r and direction a acts on others by multiplication by scaling them by r and rotating them through a.
If you work out the lengths and directions of your (10,9) and (11,13) and combine them as above, you will get the length and direction of (-7,229)
I'm working on assignment, it's about numerical method regarding to trapezoidal rule
def trapezoidalRule(F,a,b,n):
h = float(b-a)/n
f_sum = 0
for i in range(1, n, 1):
x = a + i * h
f_sum = f_sum + f(x)
return h * (0.5 * f(a) + f_sum + 0.5 * f(b))
def f(x):
return x**3
a = 2
b = 10
n = 512
print('%.16f' %trapezoidalRule(f, a, b, n))
And the output is
2496.0058593750000000
My question is, how do i get a precission like that.. without using print('%.16f' %trapezoidalRule(f, a, b, n)). I want to append the result to the list, with exact value like that..
I already tried to google it, but i found nothing related to this problem, can somebody tell me the solution if i want to it ?
Change your return statement in trapezoidalRule to be formatted with 16 points of precision, do note that this is going to cause it to become a string as if you cast it back to float you'll lose the trailing 0's.
def trapezoidalRule(F,a,b,n):
h = float(b-a)/n
f_sum = 0
for i in range(1, n, 1):
x = a + i * h
f_sum = f_sum + f(x)
return format((h * (0.5 * f(a) + f_sum + 0.5 * f(b))), '.16f')
def f(x):
return x**3
a = 2
b = 10
n = 512
See the return line in trapezoidalRule so now if I print the exact output of trapezoidalRule like so: print(trapezoidalRule(f, a, b, n)) with no formatting I get:
2496.0058593750000000
To increase precision try using decimal module
import decimal
def trapezoidalRule(F,a,b,n):
h = decimal.Decimal(float(b-a)/n)
f_sum = 0
for i in range(1, n, 1):
x = a + i * h
f_sum = f_sum + f(x)
return h * (decimal.Decimal(0.5) * f(a) + f_sum + decimal.Decimal(0.5) * f(b))
def f(x):
return decimal.Decimal(x**3)
pow(a,b,c) operator in python returns (a**b)%c . If I have values of b, c, and the result of this operation (res=pow(a,b,c)), how can I find the value of a?
Despite the statements in the comments this is not the discrete logarithm problem. This more closely resembles the RSA problem in which c is the product of two large primes, b is the encrypt exponent, and a is the unknown plaintext. I always like to make x the unknown variable you want to solve for, so you have y= xb mod c where y, b, and c are known, you want to solve for x. Solving it involves the same basic number theory as in RSA, namely you must compute z=b-1 mod λ(c), and then you can solve for x via x = yz mod c. λ is Carmichael's lambda function, but you can also use Euler's phi (totient) function instead. We have reduced the original problem to computing an inverse mod λ(c). This is easy to do if c is easy to factor or we already know the factorization of c, and hard otherwise. If c is small then brute-force is an acceptable technique and you can ignore all the complicated math.
Here is some code showing these steps:
import functools
import math
def egcd(a, b):
"""Extended gcd of a and b. Returns (d, x, y) such that
d = a*x + b*y where d is the greatest common divisor of a and b."""
x0, x1, y0, y1 = 1, 0, 0, 1
while b != 0:
q, a, b = a // b, b, a % b
x0, x1 = x1, x0 - q * x1
y0, y1 = y1, y0 - q * y1
return a, x0, y0
def inverse(a, n):
"""Returns the inverse x of a mod n, i.e. x*a = 1 mod n. Raises a
ZeroDivisionError if gcd(a,n) != 1."""
d, a_inv, n_inv = egcd(a, n)
if d != 1:
raise ZeroDivisionError('{} is not coprime to {}'.format(a, n))
else:
return a_inv % n
def lcm(*x):
"""
Returns the least common multiple of its arguments. At least two arguments must be
supplied.
:param x:
:return:
"""
if not x or len(x) < 2:
raise ValueError("at least two arguments must be supplied to lcm")
lcm_of_2 = lambda x, y: (x * y) // math.gcd(x, y)
return functools.reduce(lcm_of_2, x)
def carmichael_pp(p, e):
phi = pow(p, e - 1) * (p - 1)
if (p % 2 == 1) or (e >= 2):
return phi
else:
return phi // 2
def carmichael_lambda(pp):
"""
pp is a sequence representing the unique prime-power factorization of the
integer whose Carmichael function is to be computed.
:param pp: the prime-power factorization, a sequence of pairs (p,e) where p is prime and e>=1.
:return: Carmichael's function result
"""
return lcm(*[carmichael_pp(p, e) for p, e in pp])
a = 182989423414314437
b = 112388918933488834121
c = 128391911110189182102909037 * 256
y = pow(a, b, c)
lam = carmichael_lambda([(2,8), (128391911110189182102909037, 1)])
z = inverse(b, lam)
x = pow(y, z, c)
print(x)
The best you can do is something like this:
a = 12
b = 5
c = 125
def is_int(a):
return a - int(a) <= 1e-5
# ============= Without C ========== #
print("Process without c")
rslt = pow(a, b)
print("a**b:", rslt)
print("a:", pow(rslt, (1.0 / b)))
# ============= With C ========== #
print("\nProcess with c")
rslt = pow(a, b, c)
i = 0
while True:
a = pow(rslt + i*c, (1.0 / b))
if is_int(a):
break
else:
i += 1
print("a**b % c:", rslt)
print("a:", a)
You can never be sure that you have found the correct modulo value, it is the first value that is compatible with your settings. The algorithm is based on the fact that a, b and c are integers. If they are not you have no solution a likely combination that was the original one.
Outputs:
Process without c
a**b: 248832
a: 12.000000000000002
Process with c
a**b % c: 82
a: 12.000000000000002
I want to find the zeros of a simple function for given parameters a, b, c. I have to use the Newton-Raphson method. The problem I obtain when I compile the code is that the x variable is not defined.
from scipy import optimize
def Zeros(a, b, c, u):
return optimize.newton(a*x**2+b*x+c, u, 2*ax+b, args=(a, b, c))
a, b, c are constants of the function f and u is the starting point. So with this function I should be able to obtain a zero by specifying a, b, c and u. For instance:
print Zeros(1, -1, 0, 0.8)
But I obtain "global name 'x' is not defined".
Why does that happen?
The way most programming languages work is that they use variables (the names a, b, c, u in your code) and functions (Zeros, for instance).
When calling a function, Python expects all of the "quantities" that are input to be defined. In your case, x does not exist.
The solution is to define a function that depends on x, for the function and its derivative
from scipy import optimize
def Zeros(a,b,c,u):
def f(x, a, b, c):
return a*x**2+b*x+c
def fprime(x, a, b, c):
return 2*a*x + b
return optimize.newton(f, u, fprime=fprime,args=(a,b,c))
print(Zeros(1,-1,0,0.8))
Crude way of doing it to see what's going on!
Define a function:
def f(x):
return x ** 6 / 6 - 3 * x ** 4 - 2 * x ** 3 / 3 + 27 * x ** 2 / 2 \
+ 18 * x - 30
Define the differential:
def d_f(x):
return x ** 5 - 12 * x ** 3 - 2 * x ** 2 + 27 * x + 18
Newton-Raphson:
x = 1
d = {'x': [x], 'f(x)': [f(x)], "f'(x)": [d_f(x)]}
for i in range(0, 40):
x = x - f(x) / d_f(x)
d['x'].append(x)
d['f(x)'].append(f(x))
d["f'(x)"].append(d_f(x))
df = pd.DataFrame(d, columns=['x', 'f(x)', "f'(x)"])
print(df)
I want to create something like this programmatically:
a = (_vec, T.set_subtensor(_vec[0], _init[0]))[1]
b = (a, T.set_subtensor( a[1], a[0] * 2))[1]
c = (b, T.set_subtensor( b[2], b[1] * 2))[1]
vec_update = (c, T.set_subtensor(c[3], c[2] * 2))
test_vector = function([], outputs=vec_update)
subt = test_vector()
We got a = (_vec, T.set_subtensor(_vec[0], _init[0]))[1] so a is that whole statement. This is not doing anything yet. Then there is b = (a, T.set_subtensor( a[1], a[0] * 2))[1] which is depending on a and is another statement itself.This goes on until vec_update. I know it looks ugly but it just updates the column of a vector like col[n] = col[n-1] * 2 for col[0] = 1 returning a vector looking like this:
[[ 1. 2. 4. ..., 32. 64. 128.]]
Now Imagine I would want to do this a thousand times.. therefore I am wondering if I could generate such statements since they follow an easy pattern.
These "concatenated" statements are not evaluated until
test_vector = function([], outputs=vec_update)
which is when they are getting compiled to CUDA-code and
subt = test_vector()
does execute everything.
You can use function nesting:
def nest(f, g):
def h(x):
return f(g(x), x)
return h
expr = lambda (a,b) : a
expr = nest((lambda x, (a, b): x + (a - b)), expr)
expr = nest((lambda x, (a, b): x + (a - b)), expr)
print expr((1,2)) # prints -1
Regarding the example code, you could do something like (modifying nest to use no arguments):
def nest(f, g):
def h():
return f(g())
return h
expr = lambda: (_vec, _init)[1]
expr = nest(lambda x: T.set_subtensor(x[1], x[0] * 2)[1], expr)
expr = nest(lambda x: T.set_subtensor(x[2], x[1] * 2)[1], expr)
expr = nest(lambda x: T.set_subtensor(x[3], x[2] * 2)[1], expr)
expr = nest(lambda x: T.set_subtensor(x[4], x[3] * 2)[1], expr)
test_vector = function([], outputs=expr)
subt = test_vector()