More Decimal Places In Python - python-2.7

Here is my python code:
import math
import decimal as dec
import numpy as np
import matplotlib.pyplot as plt
c = 3e8
wave = np.array([253.6e-9,283e-9,303.9e-9,330.2e-9,366.3e-9,435.8e-9])
freq = c/wave
potent = np.array([2.6,2.11,1.81,1.47,1.10,0.57])
m,b = np.polyfit(freq,potent,1)
print m,b
e = 1.6e-19
planck = m*e
print planck
plt.plot(freq,potent,'r.')
x = np.linspace(0,10,11)
y = m*x + b
plt.plot(x,y,'b-')
To be specific, I am having trouble at the line containing y = m*x + b. The output of said line is
array([-2.27198136, -2.27198136, -2.27198136, -2.27198136, -2.27198136,
-2.27198136, -2.27198136, -2.27198136, -2.27198136, -2.27198136,
-2.27198136])
This result is due to the fact that the magnitude of slope 'm' is rather small, and the magnitude of 'b' is rather large. So, how might I overcome this obstacle?
Also, if I write plt.plot(freq,potent,'r.') and plt.plot(x,y,'b-'), will it overlay the plots?

The problem you are facing is called "Loss of significance" or "cancellation" It is rather a mathematical problem than a computer science one.
What you need to do is to change your algorithm so that cancellation does not occur any more. How to do this for simple cases is described here:
http://en.wikipedia.org/wiki/Loss_of_significance
But the change of the algorithm is not simple in some cases and may be impossible at all. If you do your calculation with more digits you do not really solve your problem. You rather postpone it. Once you change your numbers you might end up with the same problem again.

To display more decimal points add this to the end of your code:
print('%.60f' % value_x)
".60" indicates 60 decimal places to be displayed and "value_x" represents whatever value you want displayed.
I use this when I need to output the P-value as a real decimal number in addition to the default output which is in scientific notation.
Example:
In [1]: pearson_coef, p_value = stats.pearsonr(df['horsepower'], df['price'])
In [2]: print("The Pearson Correlation Coefficient is", pearson_coef, " with a P-value of P = ", p_value, "or ")
In [3]: print('%.50f' % p_value)
Out [4]: The Pearson Correlation Coefficient is 0.8095745670036559 with a P-value of P = 6.369057428260101e-48 or 0.00000000000000000000000000000000000000000000000637

Related

Function for testing system stability, which receives predicted time series as input

I want to write a function that gets a time series and a standard deviation as parameters and returns an adjusted time series which looks like a forecast.
With this function I want to test a system for stability, which gets a forecasted time series list for weather as input parameter.
My approach for such a function, which is described below:
vector<tuple<datetime, double>> get_adjusted_timeseries(vector<tuple<datetime, double>>& timeseries_original, const double stddev, const double dist_mid)
{
auto timeseries_copy(timeseries_original);
int sign = randInRange(0, 1) == 0 ? 1 : -1;
auto left_limit = normal_cdf_inverse(0.5 - dist_mid, 0, stddev);
auto right_limit = normal_cdf_inverse(0.5 + dist_mid, 0, stddev);
for (auto& pair : timeseries_copy)
{
double number;
do
{
nd_value = normal_distribution_r(0, stddev);
}
while (sign == -1 && nd_value > 0.0 || sign == 1 && nd_value < 0.0);
pair = make_tuple(get<0>(pair), get<1>(pair) + (nd_value / 100) * get<1>(pair));
if (nd_value > 0.0 && nd_value < right_limit || nd_value < 0.0 && nd_value > left_limit)
{
sign = sign == -1 ? 1 : -1;
}
}
return timeseries_copy;
}
Make a copy from the original time series, which is also from type vector<tuple<datetime, double>>
Get a random number that is either 0 or 1 and use the number to set the sign.
Use the Inverse Cumulative distribution function to get the limits, which indicate when the sign is changed. The sign is changed when the value of the copied time series is close to the original value. The implementation of the inverse CDF is shown here
For-loop for each item in the time series:
get a normal distributed value, which should be lower zero when sign == -1 and greater zero when sign == 1
adjust old value of time series according to the normal distributed
value
change sign if the normal distributed value is close to the original value.
The result for a low standard deviation, for example, can be seen here in yellow:
If the mean absolute percentage error (MAPE) of the two time series is calculated, the following relationship results:
stddev: 5 -> MAPE: ~0.04
stddev: 10 -> MAPE: ~0.08
stddev: 15 -> MAPE: ~0.12
stddev: 20 -> MAPE: ~0.16
What do you think of this approach?
Can this function be used to test a system that has to deal with predicted time series?
You want to generate time series data that behave like some existing time series data that you have from real phenomena (weather and stock exchange). That generated time series data will be fed into some system to test its stability.
What you could do is: fit some model to your exiting data, and then use that model to generate data that follow the model, and hence your existing data. Fitting data to a model yields a set of model parameters and a set of deviations (differences not explained by the model). The deviations may follow some known density function but not necessarily. Given the model parameters and deviations, you can generate data that look like the original data. Note that if the model does not explain the data well, deviations will be large, and the data generated with the model will not look like the original data.
For example, if you know your data is linear, you fit a line through them, and your model would be:
y = M x + B + E
where E is a random variable that follows the distribution of the error around the line that fits your data, and where M and B are the model parameters. You can now use that model to generate (x, y) coordinates that are rougly linear. When sampling the random variable E, you can assume that it follows some known distribution like a normal distribution, or use an histogram, to generate deviations that follow arbitrary density functions.
There are several time series models that you could use to fit your weather and stock exchange data. You could look at exponential smoothing. It has several different models. I am sure you can find many other models on Wikipedia.
If a model does not fit well your data, you can also see its parameters as random variables. In our example above, suppose that we have observed data where it seems that the slope is changing. We would fit several lines and obtain a distribution for M. We would then sample that variable along with E when generating data.

Summation under a given assumption (returning piecewise function)

I am looking to evaluate the sum an infinite geometric series in SymPy, and want to use the fact that I know the sum has to converge. (Similar to this post: How to Sum with conditions on Sympy?)
My code:
import sympy as sp
from sympy import oo
from sympy.assumptions import assuming, Q
from sympy.assumptions.assume import global_assumptions
x,k = sp.symbols('x k')
#global_assumptions.add(Q.is_true(sp.Abs(x)<1))
with assuming(Q.is_true(sp.Abs(x)<1)):
y = sp.Sum(x**k,(k,0,oo)).doit()
print y
The result is:
Piecewise((1/(-x + 1), Abs(x) < 1), (Sum(x**k, (k, 0, oo)), True))
So it seems the assumption that abs(x)<1 is not taken into account.
Using the global_assumptions (commented out here) does not give the desired result.
Concretely, how do I evaluate the sum such that the result would be 1/(1-x)?
At present, the assumptions made by the assumptions module are not used by the rest of SymPy modules, which makes them less useful than one might hope.
You can sort of fake it by using .subs like this:
y = sp.Sum(x**k, (k,0,oo)).doit().subs(sp.Abs(x) < 1, True)
which returns 1/(-x + 1).
I think this is the best one can do at present. Because this is just a literal substitution of True for a condition, rather than a logical inference, it won't work when the assumption doesn't exactly match a condition in Piecewise:
y = sp.Sum(x**k, (k,0,oo)).doit().subs(sp.Abs(x) < 1/2, True) # alas :(

Python: Returning Floats Incorrectly

I have a Python function as follows:
def point_double((xp,yp)):
s = (3.0 * pow(xp,2) - 1)/(2.0*yp) # s = 2.6
xr = pow(s,2) - (2 * xp) # xr = 0.76
yr = s * (xp - xr) - yp # yr = 0.824
return (xr,yr)
When I call point_double((3,5)) I get a return value of (0.7600000000000007, 0.8239999999999981) rather than the correct value of (0.76,0.824)
Adding print xr, yr just before the return line prints the desired result, but changing that to print (xr,yr) prints the incorrect value
Can someone explain to me why this happens, and also help me overcome this so that the function returns the desired value
Ok, its two things - firstly its that computers can't represent some numbers very well (like 1/3rd), and secondly its how "print" is manipulating your code:
So:
xr, yr = point_double((3,5))
print xr
print yr
print (xr,yr)
that will produce:
0.76
0.824
(0.7600000000000007, 0.8239999999999981)
You should consider instead printing a bit like this:
print (" x: %s y: %s" % (xr, yr))
I'm struggling to find the exact reference in print as to how it calls str() on the print, because in 2.7 its an inbuilt. Effectively by using % or string.format, you are enforcing and controlling how the float is being rendered.
zero-piraeus noted:
When you print an object, its str() method is called. The
str() method for a tuple (or any other inbuilt collection) calls repr() for each item in the collection.
Note that the actual value of xr is the longer, inaccurate one.
Edit: This is a good guide (for python 3) about how floating points are stored and other ways of printing them https://docs.python.org/3/tutorial/floatingpoint.html

How do I get imaginary numbers without using cmath when calculating the quadratic equation?

I'm currently having trouble understanding how to make imaginary numbers appear when I'm doing the quadratic equation. My assignment is to make the quadratic equation, and get imaginary numbers but I'm having an extremely difficult time getting there.
any help you can offer would be great!
Here is the code i currently have:
import math
print "Hello, please insert 3 numbers to insert into the quadratic equation."
a = input("Please enter the first value: ")
b = input("Please enter the second value: ")
c = input("Please enter the third value: ")
rootValue = b**2 - 4*a*c
if rootValue < 0:
print (-b-(rootValue)**(.5)) / (2 * a)
if rootValue > 0:
print ((-b + (rootValue)**(1/2)) /(2 * a))
if rootValue == 0:
print -b/(2*a)
please help!!! i'm so stuck right now.
I think you have to do something with the problem if rootValue < 0; but I'm not sure how to do that.
I'm also not allowed to use 'import cmath', I'm supposed to make it so that you can just do this this way.
There are a couple of problems with your code besides how to represent complex numbers. Remember that if rootValue <> 0, there are ALWAY TWO roots:
(-b +/- sqrt(rootValue)/ 2a
It doesn't matter if the rootValue is positive or negative, there's still two roots. You are branching and only providing one of the two roots in each case. No need for the first two if statements
To make rootValue complex, so that you can have complex result when you take the square root, either set it equal to complex(b2 - 4*a*c, 0) or to (b2 - 4*a*c, 0) + 0j.
You want to raise things to the 0.5 power for each of the two roots, NOT the (1/2) power, as you've done in one statement
For completeness, you may want to deal with the a = 0 case.
If you still have problems, let us know.

Why is python skipping a line?

I'm pretty new to Python (just started teaching myself a week ago), so my debugging skills are weak right now. I tried to make a program that would ask a user-submitted number of randomly-generated multiplication questions, with factors between 0 and 12, like a multiplication table test.
import math
import random
#establish a number of questions
questions = int(input("\n How many questions do you want? "))
#introduce score
score = 1
for question in range(questions):
x = random.randrange(0,13)
y = random.randrange(0,13)
#make the numbers strings, so they can be printed with strings
abc = str(x)
cba = str(y)
print("What is " + abc + "*" + cba +"?")
z = int(input("Answer here: "))
print z
a = x*y
#make the answer a string, so it can be printed if you get one wrong
answer = str(a)
if z > a or z < a:
print ("wrong, the answer is " + answer)
print("\n")
#this is the line that's being skipped
score = score - 1/questions
else:
print "Correct!"
print ("\n")
finalscore = score*100
finalestscore = str(finalscore)
print (finalestscore + "%")
The idea was that every time the user gets a question wrong, score (set to 1) goes down by 1/question,so when multiplied by 100 it gives a percentage of questions wrong. However, no matter the number of questions or the number gotten wrong, score remains 1, so finalestscore remains 100. Line 26 used to be:
if math.abs(z)-math.abs(a) != 0:
but 2.7.3 apparently doesn't acknowledge that math has an abs function.
Such a simple accumulator pattern doesn't seem like it would be an issue, even for an older version of Python. Help?
Try score = score - 1.0/questions
The problem is that you're doing integer division, which truncates to the nearest integer, so 1/questions will always give 0.
The problem is that you are using integers for all of your calculations. In particular, when you calculate 1/questions, it truncates (rounds down) to an integer because both values in the calculation are integers.
To avoid this, you could instead use 1.0/questions to make the calculations use floating point numbers instead (and not truncate)