Python: Returning Floats Incorrectly - python-2.7

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

Related

sympy - UnevaluatedExpr and commutative property - keep a float number unevaluated

I have the following expression: Bg = (pi / H)**2 + (2.405 / R)**2. In my computations I would like to keep the float number 2.405 unevaluated, otherwise I end up with long floats numbers scattered all around my expressions.
I thought I could use sympy UnevaluatedExpr to represent that float number. That worked nicely to further develop my expressions. The problem is that expressions containing UnevaluatedExpr are non-commutative, thus I cannot use methods like solve(), factor(), collect(), ... otherwise they throw errors complaining about the non-commutative nature of the expression.
The following code shows that the expression is non-commutative because I used UnevaluatedExpr.
import sympy as sp
R, H = sp.symbols("R, H", real=True, positive=True)
Bg = (sp.pi / H)**2 + (sp.UnevaluatedExpr(2.405) / R)**2
print(Bg)
print(Bg.is_commutative)
>>> 2.405**2/R**2 + pi**2/H**2
>>> False
whereas the following code shows that the expression is commutative, though the float number was evaluated:
Bg = (sp.pi / H)**2 + (2.405 / R)**2
print(Bg)
print(Bg.is_commutative)
>>> 5.784025/R**2 + pi**2/H**2
>>> True
Questions:
Can the UnevaluatedExpr and commutative behaviour be a bug?
What's the best way to deal with float number and prevent their evaluation? I thought about substituting the number with a symbol: that's fine for my simple example but if I work on bigger expressions it could quickly turn to a mess.
Yes, I would consider this to be a bug. I would suggest opening an issue about it https://github.com/sympy/sympy/issues/new.
You can use a Symbol. Another idea would be to use a class that explicitly wraps a float, like
class UnevaluatedFloat(Expr):
def __new__(cls, arg):
return Expr.__new__(cls, Float(arg))
def _eval_evalf(self, prec):
return self.args[0]._eval_evalf(prec)
def _sympystr(self, printer):
return printer.doprint(self.args[0])
This will create a class that gives the float when you call evalf but stays unevaluated otherwise. It also prints as the float. I added the str printer, but you can also define the other printing methods you care about in the same way, like _pretty and _latex and so on. Search for "printmethod" at https://docs.sympy.org/latest/modules/printing.html.
Example
>>> UnevaluatedFloat(1.0) + 1
1 + 1.0
>>> (UnevaluatedFloat(1.0) + 1).evalf()
2.00000000000000

Understanding & Converting ThinkScripts CompoundValue Function

I'm currently converting a ThinkScript indicator to C#, however, I've run into this CompoundValue function and I'm unsure how to covert it.
The documents reads :
Calculates a compound value according to following rule: if a bar
number is greater than length then the visible data value is returned,
otherwise the historical data value is returned. This function is used
to initialize studies with recursion.
Example Use:
declare lower;
def x = CompoundValue(2, x[1] + x[2], 1);
plot FibonacciNumbers = x;
My interpretation:
Based on description and example. It appears we are passing a calculation in x[1] + x[2] and it performing this calculation on the current bar and the previous bar (based on first param of 2). I'm unsure what the parameter 1 is for.
My Question:
Please explain what this function is actually doing. If possible, please illustrate how this method works using pseudo-code.
For the TLDR; crowd, some simple code that hopefully explains what the CompoundValue() function is trying to do, and which might help in converting it's functionality:
# from: Chapter 12. Past/Future Offset and Prefetch
# https://tlc.thinkorswim.com/center/reference/thinkScript/tutorials/Advanced/Chapter-12---Past-Offset-and-Prefetch
# According to this tutorial, thinkScript uses the highest offset, overriding
# all lower offsets in the script - WOW
declare lower;
# recursive addition using x[1] is overridden by 11 in the plot for
# Average(close, 11) below; SO `x = x[1] + 1` becomes `x = x[11] + 1`
def x = x[1] + 1;
# using CompoundValue, though, we can force the use of the *desired* value
# arguments are:
# - length: the number of bars for this variable's offset (`1` here)
# - "visible data": value to use IF VALUES EXIST for a bar (a calculation here)
# - "historical data": value to use IF NO VALUE EXISTS for a bar (`1` here)
def y = CompoundValue(1, y[1] + 1, 1);
# *plotting* this Average statement will change ALL offsets to 11!
plot Average11 = Average(close, 11);
# `def`ing the offset DOES NOT change other offsets, so no issue here
# (if the `def` setup DID change the offsets, then `x[1]` would
# become `x[14]`, as 14 is higher than 11. However, `x[1]` doesn't change.
def Average14 = Average(close, 14);
plot myline = x;
plot myline2 = y;
# add some labels to tell us what thinkScript calculated
def numBars = HighestAll(BarNumber());
AddLabel(yes, "# Bars on Chart: " + numBars, Color.YELLOW);
AddLabel(yes, "x # bar 1: " + GetValue(x, numBars), Color.ORANGE);
AddLabel(yes, "x # bar " + numBars + ": " + x, Color.ORANGE);
AddLabel(yes, "y # bar 1: " + GetValue(y, numBars), Color.LIGHT_ORANGE);
AddLabel(yes, "y # bar " + numBars + ": " + y, Color.ORANGE);
Now, some, er, lots of details...
First, a quick note on "offset" values:
thinkScript, like other trading-related languages, uses an internal looping system. This is like a for loop, iterating through all the "periods" or "bars" on a chart (eg, 1 bar = 1 day on a daily chart; 1 bar = 1 minute on a 1 minute intraday chart, etc). Every line of code in thinkScript is run for each and every bar in the chart or length of time specified in the script.
As noted by the OP, x[1] represents an offset of one bar before the current bar the loop is processing. x[2] represents two bars before the current bar, and so on. Additionally, it's possible to offset into the future by using negative numbers: x[-1] means one bar ahead of the current bar, for example.
These offsets work similarly to the for loop in C#, except they're backwards: x[0] in C# would represent the current x value, as it would in thinkScript; however, moving forward in the loop, x[1] would be the next value, and x[-1] wouldn't exist because, well, there is no past value before 0. (In general, of course! One can definitely loop with negative numbers in C#. The point is that positive offset indices in thinkScript represent past bars, while negative offset indices in thinkScript represent future bars - not the case in C#.)
Also important here is the concept of "length": in thinkScript, length parameters represent the distance you want to go - like the offset, but a range instead of one specific bar. In my example code above, I used the statement plot Average11 = Average(close, 11); In this case, the 11 parameter represents plotting the close for a period of 11 bars, ie, offsets x[0] through x[10].
Now, to explain the CompoundValue() function's purpose:
The Chapter 12. Past/Future Offset and Prefetch thinkScript tutorial explains that thinkScript actually overrides smaller offset or length values with the highest value in a script. What that means is that if you have two items defined as follows:
def x = x[1] + 1;
plot Average11 = Average(close, 11);
thinkScript will actually override the x[1] offset with the higher length used in the Average statement - therefore causing x[1] to become x[11]!
Yike! That means that the specified offsets, except the highest offset, mean nothing to thinkScript! So, wait a minute - does one have to use all the same offsets for everything, then? No! This is where CompoundValue() comes in...
That same chapter explains that CompoundValue() allows one to specify an offset for a variable that won't be changed, even if a higher offset exists.
The CompoundValue() function, with parameter labels, looks like this:
CompoundValue(length, "visible data", "historical data")
As the OP noted, this isn't really particularly clear. Here's what the parameters represent:
length: the offset number of bars for this variable.
In our example, def x = x[1] + 1, there is a 1 bar offset, so our statement starts as CompoundValue(length=1, ...). If instead, it was a larger offset, say 14 bars, we'd put CompoundValue(length=14, ...)
"visible data": the value or calculation thinkScript should perform if DATA IS AVAILABLE for the current bar.
Again, in our example, we're using a calculation of x[1] + 1, so CompoundValue(length=1, "visible data"=(x[1] + 1), ...). (Parentheses around the equation aren't necessary, but may help with clarity.)
"historical data": the value to use if NO DATA IS AVAILABLE for the current bar.
In our example, if no data is available, we'll use a value of 1.
Now, in thinkScript, parameter labels aren't required if the arguments are in order and/or defaults are supplied. So, we could write this CompoundValue statement like this without the labels:
def y = CompoundValue(1, y[1] + 1, 1);
or like this with the labels:
def y = CompoundValue(length=1, "visible data"=(y[1] + 1), "historical data"=1);
(Note that parameter names containing spaces have to be surrounded by double quotes. Single-word parameter names don't need the quotes. Also, I've placed parens around the equation just for the sake of clarity; this is not required.)
In summary: CompoundValue(...) is needed to ensure a variable uses the actual desired offset/number of bars in a system (thinkScript) that otherwise overrides the specified offsets with a higher number if present.
If all the offsets in a script are the same, or if one is using a different programming system, then CompoundValue() can simply be broken down into its appropriate calculations or values, eg def x = x[1] + 1 or, alternatively, an if/else statement that fills in the values desired at whatever bars or conditions are needed.
Please let me provide two equivalent working versions of the code in thinkscript itself. We use this approach to prove equivalence by subtracting the equivalent outputs from each other - the result should be 0.
# The original Fibonacci code with a parameter "length" added.
# That parameter is the first parameter of the CompoundValue function.
declare lower;
def length = 2;
def x = CompoundValue(length, x[1] + x[2], 1);
# plot FibonacciNumbers = x;
# Equivalent code using the `if` statement:
def y;
if(BarNumber() > length){
# Visible data. This is within the guarded branch of the if statement.
# Historical data y[1] (1 bar back) and y[2] (2 bars back) is available
y = y[1] + y[2];
}else{
# Not enough historical data so we use the special case satisfying the
# original rule.
y = 1;
}
plot FibonacciNumbersDiff = y - x;
Thinkscript "recursion" is a somewhat inflated term. The function name CompoundValue is not very helpful so it may create confusion.
The version using the if statement is more useful in general because when walking through the time series of bars, we often need a program structure with multiple nested if statements - this cannot be done with the CompoundValue function. Please see my other articles which make use of this in the context of scanning.
In Java, using the same structure, it looks like this:
int size = 100;
int length = 2;
int[] values = new int[size];
for(int index = 1; index < size; index++){
if(index > length){
values[index] = values[index - 1] + values[index - 2];
}else{
values[index] = 1;
}
}
The fundamental difference is the for loop which is not present in the thinkscript code. thinkscript provides the loop in a kind of inversion of control where it executes user code multiple times, once for each bar.

More Decimal Places In Python

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

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)

python and weierstrass function

based on this function. I'm trying to create two empty arrays (one for x and other for y), which later I will use to plot in python. But before anything this is what I have so far...
import math
x1=-2.0
x2=2.0
arr1 = []
arr2 = []
i=0
n=10
delta=(x2-x1)/n
for i in range (0,n+1):
x=x1+delta*i
arr1.append(x)
print arr1
# I have not called the w function yet
the code above creates a list of 10 numbers for now to keep it simple. Then it will send the elements of the array to the function below and compute the equation with certain numbers(infinite loop).
#This function will create the array list for y
import math
def w(x, limit):# the limit here to compare when the number is really small
suma = 0.0
sumb = 0.0
m=1
x=0
suma=suma+((1/(math.pow(2,m))*(math.sin(math.pow(2,m)*x)))
sumb=suma+((1/(math.pow(2,m+1))*(math.sin(math.pow(2,m+1)*x))) # I'm having a
#syntax error
#here
x+=0
if (abs (suma-sumb)<limit):
break:
else m+=1:
if (m<20):
break:
I will appreciate any help with my syntax errors or any suggestion. I just hope I was clear enough.
Thanks ahead of time
The syntax error is actually on the previous line, where the parenthesis are not balanced. You need an extra ) at the end of that line (and at the one you indicated as giving an error too btw).
There are also a few other issues
suma is set to zero, so suma = suma + ... is the same as suma = ..., but I'm guessing you still need to add while loop before this line.
On the line indicated, you have sumb = suma +, which is probably a copy/paste mistake.
The code block starting at x+=0 is indented by only 3 spaces instead of 4. This is probably not the case in your actual code, but if it is, Python will complain about that too.
else m+=1: should be else: m+=1 (colon directly after else, not at the end of the line.
break: should just be break (without to colon).