How to numerical evaluate trigonometric functions as a multiple of pi using the sympy package? - sympy

Is there a way to evaluate trigonometric functions as a multiple of pi using sympy? You can use the N function to get a numerical evaluation, but I'm searching for a function which will give me values like a * pi (a = constant).

SymPy already does that for inverse trigonometric functions. But to get a symbolic (as opposed to floating point) result, you need to provide symbolic (as opposed to floating point) input. Compare
>>> asin(1/2)
0.523598775598299
>>> asin(Rational(1, 2))
pi/6
Here 1/2 produces a Python float 0.5, and the result is another Python float. But Rational(1, 2) constructs a SymPy object representing a rational number, and then evaluation is done symbolically.
More in Python numbers vs. SymPy Numbers

Related

Calculating non-decimal digit sequences with sympy

Is there a direct way to generate the sequence of digits in an arbitrary non-decimal base for irrational numeric values directly in sympy?
What I need is to e.g. obtain the the first 1024 binary digits of pi in an array-like data structure; but couldn't find such a function despite intensive search.
For those who care: the intended use is for generating test-instances for combinatorial optimization whose generation can easily be communicated.
I know how to do it algorithmically, but would prefer to use a builtin function.
Something like this:
In [6]: from sympy import pi
In [7]: bin(pi.evalf(1000)._mpf_[1])[2:1024+2]
Out[7]: '1100100100001111110110101010001000100001011010001100001000110100110001001100011001100010100010111000000011011100000111001101000100101001000000100100111000001000100010100110011111001100011101000000001000001011101111101010011000111011000100111001101100100010010100010100101000001000011110011000111000110100000001001101110111101111100101010001100110110011110011010011101001000011000110110011000000101011000010100110110111110010010111110001010000110111010011111110000100110101011011010110110101010001110000100100010111100100100001011011010101110110011000100101111001111110110001101111010001001100010000101110100110100110001101111110110101101011000010111111111101011100101101101111010000000110101101111110110111101110001110000110101111111011010110101000100110011111101001011010111010011111001001000001000101111100010010110001111111100110010010010010100001100110010100011110110011100100010110110011110111000010000000000111110010111000101000010110001110111111000001011001100011011010010010000011011000011100010101011101001110011010'

Arbitrary precision gamma function

I'm implementing an arbitrary precision arithmetic library in C++ and I'm pretty much stuck when implementing the gamma function.
By using the equivalences gamma(n) = gamma(n - 1) * n and gamma(n) = gamma(n + 1) / n, respectively, I can obtain a rational number r in the range (1; 2] for all real values x.
However, I don't know how to evaluate gamma(r). For the Lanczos approximation (https://en.wikipedia.org/wiki/Lanczos_approximation), I need precomputed values p which happen to calculate a factorial of a non-integer value (?!) and can't be calculated dynamically with my current knowledge... Precomputing values for p wouldn't make much sense when implementing an arbitrary precision library.
Are there any algorithms that compute gamma(r) in a reasonable amount of time with arbitrary precision? Thanks for your help.
Spouge's approximation is similar to Lanczos's approximation, but probably easier to use for arbitrary precision, as you can set the desired error.
Lanczos approximation doesn't seem too bad. What exactly do you suspect?
Parts of code which calculate p, C (Chebyshev polynomials) and (a + 1/2)! can be implemented as stateful objects so that, for example, you can calculate p(i) from p(i-1) and Chebyshev coefficients and be computed once, maintaining their matrix.

Python trig functions not returning matched results

I came across something rather interesting while I am playing around with the math module for trigonometric calculations using tan, sin, and cos.
As stated is all math textbooks, online source, and courses, the following is true:
tan(x) = sin(x) / cos(x)
Although I came across some precision errors while using the three trig functions with the following:
from math import tan, sin, cos
theta = -30
alpha = tan(theta)
omega = sin(theta) / cos(theta)
print(alpha, omega)
print(alpha == omega)
>>> (6.405331196646276, 6.4053311966462765)
>>> (False)
I have tried a couple of different values for theta and the last digit of the results has been off by a tiny bit.
Is there something that I am missing?
This issue is because of the finite floating point precision (not all real numbers can be represented exactly and not all calculations with them are precise). An accessible guide is in the Python docs.
Using the default, "double precision" floating point representation, you can never hope for better than about 15 decimal place precision and calculations involving such numbers will tend to degrade this precision (the rounding error refered to in the above comment). In the same way, you get False from the following:
In [1]: 0.01 == (0.1)**2
Out[1]: False
because the Python isn't squaring 0.1 but the "nearest representable number" to 0.1, which is neither 0.01 nor the nearest representable number to 0.01.
D Stanley has given the correct way to test for "equality" within some absolute tolerance: (abs(a-b) < tol) where tol is some small number you choose to fit your expected precision.
As you have discovered, there is a level of imprecision when comparing floating point numbers. A common way to test for "equality" is to determine a reasonable amount of difference you want to accept (commonly called "epsilon") an compare the difference between the two numbers against that maximum error:
epsilon = 1E-14
print(alpha, omega)
print(alpha == omega)
print(abs(alpha - omega) < epsilon)
First you should notice that the arguments of trigonometric functions are given in arc length, not in degree. Thus theta=-30 refers to an angle of -30*180/pi in degrees.
Second, the processor, and thus the calling math library, has separate internal procedures for the computation of tan and (sin, cos). The extra division operation loses 1/2 to 1 bit of precision, which explains the difference in results.

Why is sin(pi/4) different from cos(pi/4) in python? [duplicate]

This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed 8 years ago.
I wonder why this statement is evaluated false:
>>> from numpy import sin,cos,pi
>>> sin(pi/4)==cos(pi/4)
False
in fact sine and cosine of pi/4 should be √ 2 / 2. What's happen? And how to avoid this problem?
If you look at what the results actually are:
>>> sin(pi/4)
0.70710678118654746
>>> cos(pi/4)
0.70710678118654757
You will note that they are very, very close, but not exactly the same. Due to these kinds of floating point representation issues, it is usual to use a threshold to compare values that should be the same:
>>> abs(sin(pi/4) - cos(pi/4)) < 1e-9
True
Fun fact: using numpy's sqrt, too:
>>> sqrt(2)/2
0.70710678118654757
>>> sqrt(2)/2 == cos(pi/4)
True
Because floating point representation isn't always exact and functions like cos and sin are calculated by approximate numerical methods, it is unreasonable to imagine that the results will be bitwise identical. On my machine, I get this when I compare sine and cosine
>import numpy
>x=numpy.sin(numpy.pi/4)
>y=numpy.cos(numpy.pi/4)
>print numpy.abs(x-y)/numpy.max(x,y)
1.57009245868e-16
ie. the relative error is very close to the IEEE 754 double precision epsilon. If you need to compare two floating point values, compare a delta value to a tolerance, or use numpy.allclose()

C++ Cosine Problem

I have the following code using C++:
double value = .3;
double result = cos(value);
When I look at the values in the locals window for "value" it shows 0.2999999999
Then, when I get the value of "result" I get: 0.95533648912560598
However, when I run cos(.3) on the computers calculator I get: .9999862922474
So clearly there is something that I am doing wrong.
Any thoughts on what might be causing the difference in results?
I am running Win XP on an Intel processor.
Thanks
The difference in results is because:
Your computer's calculator is returning the cosine of an angle specified in degrees.
The C++ cos() function is returning cosine of an angle specified in radians.
The .2999999999 is due to the way floating point numbers are handled in computers. .3 cannot be represented exactly in a double. For details, I recommend reading What Every Computer Scientist Should Know about Floating Point Arithmetic.
cos(.3 radians) = 0.95533...
cos(.3 degrees) = 0.99998...
cos(0.3) = 0.99998629224742679269138848004408 using degrees
cos(0.3) = 0,95533648912560601964231022756805 using radians
When I look at the values in the locals window for "value" it shows 0.2999999999
Long story short, your calculator uses decimal arithmetic, while your C++ code uses binary arithmetic (double is a binary floating-point number). Decimal number 0.3 cannot be represented exactly as a binary floating-point number. Read What Every Computer Scientist Should Know About Floating-Point Arithmetic, that will explain all implications in more detail.
Your calculator is using degrees. For example:
>>> import math
>>> math.cos (.3)
0.95533648912560598
>>> math.cos (.3 * math.pi / 180) # convert to degrees
0.99998629224742674
C++ does not exactly represent floating point numbers due to the insane amount of storage that would be required to get the infinite precision necessary. For a demonstration of this, try the following:
double ninth = 1.0/9.0;
double result = 9.0 * ninth;
This should yield a value in result of .99999999999
So, in essence, you need to compare floating point values within a small epsilon (I tend to use 1e-7). You can do a strict bit-by-bit comparison, but this consists of converting the memory used by the floating point to an array of characters of length sizeof(float), then comparing the characters.
Another thing to check would be whether or not you are using degrees. The computer's calculator uses degrees for its cosine calculation (notice how the result from the calculator is .99999..., which is very close to 1. The cosine of zero is 1 exactly), whereas the cosine function offered in <math> is in radians. Try multiplying your value by PI/180.0 and seeing if the result is more inline with your expectations.