Sin pi : give wrong result [duplicate] - python-2.7

This question already has answers here:
floating point in python gives a wrong answer [duplicate]
(3 answers)
why am I getting an error using math.sin(math.pi) in python?
(1 answer)
Closed 5 years ago.
i tried to create polar array with math module ; but math.sin(math.pi) always give wrong result.
with python 2.7 or 3.5 the same wrong result :
import math
m = math.radians(180)
print (math.sin(m))
pi = math.pi
print (pi)
print (math.sin(pi))
1.2246467991473532e-16
3.141592653589793
1.2246467991473532e-16
this is my code and the same error:
import math
a = 180 #(degree)
r = 10
n = 8
b = float(a)/n
pi = math.radians(180)
print math.sin(pi)
for i in range(0,2*n+1):
print i
c1 = b*i
print c1
c2 = c1*math.pi/a #c : radians
print c2
sinb = math.sin(c2)
cosb = math.cos(c2)
x = r*sinb
y = r*cosb
#print (x, y)
the threads mentioned in the comment give explanation not a solution ; so i don't need explanation how and why without solution to solve my problem and the answer from cody give me the solution.
if you think that the other threads show the answer mention in these threads that are duplicate.

Since pi is an irrational number and goes on forever, the Python version is not actually exact pi. As a result, the sin of almost-pi is almost-0. Basically you can chalk it up to a Python rounding error.
Here's some more information on the topic in general:
Floating Point Arithmetic: Issues and Limitations
why am I getting an error using math.sin(math.pi) in python?
I suggest you put some rounding in to the nearest N units that will suffice for your module. The numerical value of what you got is 0.000000000000000122. Five digits after the decimal should be good for almost anything you could need the module for.

Related

Solve a nonlinear system of equation via sympy

I have a system of ODE and want to find equilibrium points by using nonlinsolve() but when i run it by jubyter or spyder the program keep running without any result.
N,x1,x2,x3,x4,y1,y2,r1,r2,r3,r4,eta1,eta2,eta3,eta4,R,c1,c2,c3,c4,a11,a12,a21,a22,a31,a32,a41,a42,b12,h,h11,h12,h21,h22,h31,h32,h41,h42,s1,s2,s3,s4,epsilon1,epsilon2,omega1,omega2,K11,K22,beta11,beta21,beta31,beta41,beta12,beta22,beta32,beta42,gamma12=sp.symbols('x1,x2,x3,x4,y1,y2,r1,r2,r3,r4,eta1,eta2,eta3,eta4,N,R,c1,c2,c3,c4,a11,a12,a21,a22,a31,a32,a41,a42,b12,h,h11,h12,h21,h22,h31,h32,h41,h42,s1,s2,s3,s4,epsilon1,epsilon2,omega1,omega2,K11,K22,beta11,beta21,beta3a,beta41,beta12,beta22,beta32,beta42,gamma12')
F2=x1*(r1*(1-(eta1*x1+eta2*x2+eta3*x3+eta4*x4)/N)-(a11*y1)/(y1+a11*h11*x1)-(a12*y2)/(y2+a12*h12*x1))+s1
F3=x2*(r2*(1-(eta1*x1+eta2*x2+eta3*x3+eta4*x4)/N)-(a21*y1)/(y1+a21*h21*x2)-(a22*y2)/(y2+a22*h22*x2))+s2
F4=x3*(r3*(1-(eta1*x1+eta2*x2+eta3*x3+eta4*x4)/N)-(a31*y1)/(y1+a31*h31*x3)-(a32*y2)/(y2+a32*h32*x3))+s3
F5=x4*(r4*(1-(eta1*x1+eta2*x2+eta3*x3+eta4*x4)/N)-(a41*y1)/(y1+a42*h41*x4)-(a42*y2)/(y2+a42*h42*x4))+s4
F6=y1*(-epsilon1*(1+(y1+omega2*y2)/K11)-(b12*y2)/(y2+b12*h*y1)\
+beta11*(a11*x1)/(y1+a11*h11*x1)\
+beta21*(a21*x2)/(y1+a21*h21*x2)\
+beta31*(a31*x3)/(y1+a31*h31*x3)\
+beta41*(a41*x4)/(y1+a41*h41*x4))
F7=y2*(-epsilon2*(1+(omega1*y1+y2)/K22)+gamma12*(b12*y1)/(y2+b12*h*y1)\
+beta12*(a12*x1)/(y2+a12*h12*x1)\
+beta22*(a22*x2)/(y2+a22*h22*x2)\
+beta32*(a32*x3)/(y2+a32*h32*x3)\
+beta42*(a42*x4)/(y2+a42*h42*x4))
equ=(F2,F3,F4,F5,F6,F7)
sol=nonlinsolve(equ,x1,x2,x3,x4,y1,y2)
print(sol)
Is it possible to get the solution in terms of parameters?
Your system of equations can be recast as multivariate polynomial system if you multiply through by all of the denominators. Doing this for example in the case of F2 you would get
In [26]: F2.as_numer_denom()[0]
Out[26]:
s₁⋅x₁⋅(a₁₁⋅h₁₁⋅x₂ + y₂)⋅(a₁₂⋅h₁₂⋅x₂ + r₁) + x₂⋅(-a₁₁⋅x₁⋅y₂⋅(a₁₂⋅h₁₂⋅x₂ + r₁) - a₁₂⋅r₁⋅x₁⋅(a₁₁⋅h₁₁⋅x₂ + y₂) + r₂⋅(a₁₁⋅h₁₁⋅x₂ + y₂
)⋅(a₁₂⋅h₁₂⋅x₂ + r₁)⋅(-N⋅y₁ - η₂⋅x₂ - η₃⋅x₃ - η₄⋅x₄ + x₁))
We can see from here that the polynomial is of order 5 since it has terms like x2**3*N*y1 so broadly you have a system of 7 polynomials not of low order. I expect that a general closed form solution will not be possible unless you are lucky.

Declaring variables in Python 2.7x to avoid issues later

I am new to Python, coming from MATLAB, and long ago from C. I have written a script in MATLAB which simulates sediment transport in rivers as a Markov Process. The code randomly places circles of a random diameter within a rectangular area of a specified dimension. The circles are non-uniform is size, drawn randomly from a specified range of sizes. I do not know how many times I will step through the circle placement operation so I use a while loop to complete the process. In an attempt to be more community oriented, I am translating the MATLAB script to Python. I used the online tool OMPC to get started, and have been working through it manually from the auto-translated version (was not that helpful, which is not surprising). To debug the code as I go, I use the
MATLAB generated results to generally compare and contrast against results in Python. It seems clear to me that I have declared variables in a way that introduces problems as calculations proceed in the script. Here are two examples of consistent problems between different instances of code execution. First, the code generated what I think are arrays within arrays because the script is returning results which look like:
array([[ True]
[False]], dtype=bool)
This result was generated for the following code snippet at the overlap_logix operation:
CenterCoord_Array = np.asarray(CenterCoordinates)
Diameter_Array = np.asarray(Diameter)
dist_check = ((CenterCoord_Array[:,0] - x_Center) ** 2 + (CenterCoord_Array[:,1] - y_Center) ** 2) ** 0.5
radius_check = (Diameter_Array / 2) + radius
radius_check_update = np.reshape(radius_check,(len(radius_check),1))
radius_overlap = (radius_check_update >= dist_check)
# Now actually check the overalp condition.
if np.sum([radius_overlap]) == 0:
# The new circle does not overlap so proceed.
newCircle_Found = 1
debug_value = 2
elif np.sum([radius_overlap]) == 1:
# The new circle overlaps with one other circle
overlap = np.arange(0,len(radius_overlap), dtype=int)
overlap_update = np.reshape(overlap,(len(overlap),1))
overlap_logix = (radius_overlap == 1)
idx_true = overlap_update[overlap_logix]
radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)
A similar result for the same run was produced for variables:
radius_check_update
radius_overlap
overlap_update
Here is the same code snippet for the working MATLAB version (as requested):
distcheck = ((Circles.CenterCoordinates(1,:)-x_Center).^2 + (Circles.CenterCoordinates(2,:)-y_Center).^2).^0.5;
radius_check = (Circles.Diameter ./ 2) + radius;
radius_overlap = (radius_check >= distcheck);
% Now actually check the overalp condition.
if sum(radius_overlap) == 0
% The new circle does not overlap so proceed.
newCircle_Found = 1;
debug_value = 2;
elseif sum(radius_overlap) == 1
% The new circle overlaps with one other circle
temp = 1:size(radius_overlap,2);
idx_true = temp(radius_overlap == 1);
radius = distcheck(1,idx_true) - (Circles.Diameter(1,idx_true)/2);
In the Python version I have created arrays from lists to more easily operate on the contents (the first two lines of the code snippet). The array within array result and creating arrays to access data suggests to me that I have incorrectly declared variable types, but I am not sure. Furthermore, some variables have a size, for example, (2L,) (the numerical dimension will change as circles are placed) where there is no second dimension. This produces obvious problems when I try to use the array in an operation with another array with a size (2L,1L). Because of these problems I started reshaping arrays, and then I stopped because I decided these were hacks because I had declared one, or more than one variable incorrectly. Second, for the same run I encountered the following error:
TypeError: 'numpy.ndarray' object is not callable
for the operation:
radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)
which occurs at the bottom of the above code snippet. I have posted the entire script at the following link because it is probably more useful to execute the script for oneself:
https://github.com/smchartrand/MarkovProcess_Bedload
I have set-up the code to run with some initial parameter values so decisions do not need to be made; these parameter values produce the expected results in the MATLAB-based script, which look something like this when plotted:
So, I seem to specifically be having issues with operations on lines 151-165, depending on the test value np.sum([radius_overlap]) and I think it is because I incorrectly declared variable types, but I am really not sure. I can say with confidence that the Python version and the MATLAB version are consistent in output through the first step of the while loop, and code line 127 which is entering the second step of the while loop. Below this point in the code the above documented issues eventually cause the script to crash. Sometimes the script executes to 15% complete, and sometimes it does not make it to 5% - this is due to the random nature of circle placement. I am preparing the code in the Spyder (Python 2.7) IDE and will share the working code publicly as a part of my research. I would greatly appreciate any help that can be offered to identify my mistakes and misapplications of python coding practice.
I believe I have answered my own question, and maybe it will be of use for someone down the road. The main sources of instruction for me can be found at the following three web pages:
Stackoverflow Question 176011
SciPy FAQ
SciPy NumPy for Matlab users
The third web page was very helpful for me coming from MATLAB. Here is the modified and working python code snippet which relates to the original snippet provided above:
dist_check = ((CenterCoordinates[0,:] - x_Center) ** 2 + (CenterCoordinates[1,:] - y_Center) ** 2) ** 0.5
radius_check = (Diameter / 2) + radius
radius_overlap = (radius_check >= dist_check)
# Now actually check the overalp condition.
if np.sum([radius_overlap]) == 0:
# The new circle does not overlap so proceed.
newCircle_Found = 1
debug_value = 2
elif np.sum([radius_overlap]) == 1:
# The new circle overlaps with one other circle
overlap = np.arange(0,len(radius_overlap[0]), dtype=int).reshape(1, len(radius_overlap[0]))
overlap_logix = (radius_overlap == 1)
idx_true = overlap[overlap_logix]
radius = dist_check[idx_true] - (Diameter[0,idx_true] / 2)
In the end it was clear to me that it was more straightforward for this example to use numpy arrays vs. lists to store results for each iteration of filling the rectangular area. For the corrected code snippet this means I initialized the variables:
CenterCoordinates, and
Diameter
as numpy arrays whereas I initialized them as lists in the posted question. This made a few mathematical operations more straightforward. I was also incorrectly indexing into variables with parentheses () as opposed to the correct method using brackets []. Here is an example of a correction I made which helped the code execute as envisioned:
Incorrect: radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)
Correct: radius = dist_check[idx_true] - (Diameter[0,idx_true] / 2)
This example also shows that I had issues with array dimensions which I corrected variable by variable. I am still not sure if my working code is the most pythonic or most efficient way to fill a rectangular area in a random fashion, but I have tested it about 100 times with success. The revised and working code can be downloaded here:
Working Python Script to Randomly Fill Rectangular Area with Circles
Here is an image of a final results for a successful run of the working code:
The main lessons for me were (1) numpy arrays are more efficient for repetitive numerical calculations, and (2) dimensionality of arrays which I created were not always what I expected them to be and care must be practiced when establishing arrays. Thanks to those who looked at my question and asked for clarification.

Fortran arctan subroutine is not working as expected

I'm generally new to Fortran, and I have a project in which my professor wants the class to try to find pi. To do this he wants us to create our own arctan subroutine and use this specific equation: pi = 16*arctan(1/5) - 4*arctan(1/239).
Because the professor would not let me use the built in ATAN function, I made a subroutine that approximates it:
subroutine arctan(x,n,arc)
real*8::x, arc
integer::n, i
real*8::num, nm2
arc = 0.0
do i=1,n,4
num = i
nm2 = num+2
arc = arc+((x**num)/(num)) - (x**(nm2)/(nm2))
enddo
end subroutine arctan
This subroutine is based off of the Taylor series for arctan approximation, and seemed to work perfectly because I tested it by calling this.
real*8:: arc=0.0, approx
call arctan(1.d0,10000000,arc)
approx = arc*4
I called this from my main program which should return pi and I got
approx = 3.1415926335902506
which is close enough for me. The problem occurs when I try to do
pi = 16*arctan(1/5) - 4*arctan(1/239). I tried this:
real*8:: first, second
integer:: n=100
call arctan((1.d0/5.d0), n, arc)
first = 16*arc
call arctan((1.d0/239.d0), n, arc)
second = 4.d0*arc
approx = first - second
and somehow approx = 1.67363040082988898E-002, which is obviously not pi. arc resets with every call of the arctan subroutine so I know that isn't the problem. I think the problem is in how I'm calling the subroutine before I declare first and second, but I don't know what I could do to improve them.
What am I doing wrong?
EDIT:
I actually solved the problem and the actual problem was just fortran decided that it did not want to do approx = first - second
and was making it so that approx == second I have no idea why, but I solved the problem by replacing that statement with the following:
approx = (second-first)
approx = approx *(-1)
and as stupid as it looks, it works perfectly now, with a result of 3.1415926535897940!
The problem results from different types (single/double precsion) of the
variable arc in the call of arctan and the implementation of the subroutine. The iteration count of 10000... is way too much and may cause numerical problems, just 100 is more than enough (and much faster...).
Tip: always use implicit none for all progs and procedures. Here the compiler would have immediately told you that you forgot to declare arc...
Just make it double precision in the main program and you will get the desired answer.

using python 3.5 code in python 2.7 gives different answer

a=[[2,5],[1,3]]
b=[5,1]
r=len(a)
x=[1,1]
def func():
tol=.00000000001;l=0;ite=10000
fnd=0
while(l<ite and fnd==0):
j=0
while(j<r):
temp=b[j]
k=0
while(k<r):
if (j!=k):
temp=temp-a[j][k]*x[k]
k=k+1
c=temp/a[j][j]
if (abs(x[j]-c)<=tol):
fnd=1
break
x[j]=c
j=j+1
l=l+1
if l==ite:
print ("Iterations are over")
print(x)
func()
running this code in python 3.5 gives correct answer [9.999999999858039, -2.9999999999432156]
but gives answer [7,-2] in python 2.7. Why?
This is implementation of Gauss-Seidel method to find solution of system of equations using matrix.
The difference is in the way python 2 and python 3 handle the / operator in the line c=temp/a[j][j]. In python 2, / performs integer division, while in python 3 it performs floating point division.
Converting temp to a float before the division (i..e, c=float(temp)/a[j][j]) will ensure you get the right answer in both versions.

How can I simulate GNU C Library drem / remainder function in Google App Engine Python 2.7 runtime?

The GNU C Library has the function drem (alias remainder).
How can I simulate this function just using the modules supported by Google App Engine Python 2.7 runtime?
From the GNU manual for drem:
These functions are like fmod except that they round the internal quotient n to the nearest integer instead of towards zero to an integer. For example, drem (6.5, 2.3) returns -0.4, which is 6.5 minus 6.9.
From the GNU manual for fmod:
These functions compute the remainder from the division of numerator by denominator. Specifically, the return value is numerator - n * denominator, where n is the quotient of numerator divided by denominator, rounded towards zero to an integer. Thus, fmod (6.5, 2.3) returns 1.9, which is 6.5 minus 4.6.
Reading the documentation the following Python code should work:
def drem(x, y):
n = round(x / y)
return x - n * y
However with Python, drem(1.0, 2.0) == -1.0 and with C drem(1.0, 2.0) == 1.0. Note Python returns negative one and C returns positive one. This is almost certainly an internal difference in rounding floats. As far as I can tell both functions perform the same otherwise where parameters 2 * x != y.
How can I make my Python drem function work the same as its C equivalent?
The key to solving this problem is to realise that the drem/remainder function specification requires the internal rounding calculation to round to half even.
Therefore we cannot use the built-in round function in Python 2.x as it rounds away from 0. However the round function in Python 3.x has changed to round to half even. So the following Python 3.x code will be equivalent to the GNU C Library drem function but will not work in Python 2.x:
def drem(x, y):
n = round(x / y)
return x - n * y
To achieve the same with Python 2.x we can use the decimal module and its remainder_near function:
import decimal
def drem(x, y):
xd = decimal.Decimal(x)
yd = decimal.Decimal(y)
return float(xd.remainder_near(yd))
EDIT: I just read your first comment and see that you cannot use the ctypes module. Anyways, I learned a lot today by trying to find an answer to your problem.
Considering that numpy.round() rounds values exactly halfway between rounded decimal values to the next even integer, using numpy is not a good solution.
Also, drem internally calls this MONSTER function, which should be hard to implement in Python.
Inspired by this article, I would recommend you to call the drem function from the math library directly. Something along these lines should do the trick:
from ctypes import CDLL
# Use the C math library directly from Python
# This works for Linux, but the version might differ for some systems
libm = CDLL('libm.so.6')
# For Windows, try this instead:
# from ctypes import cdll
# libm = cdll.libc
# Make sure the return value is handled as double instead of the default int
libm.drem.restype = c_double
# Make sure the arguments are double by putting them inside c_double()
# Call your function and have fun!
print libm.drem(c_double(1.0), c_double(2.0))