This question already has answers here:
How do I put a variable’s value inside a string (interpolate it into the string)?
(9 answers)
Closed 2 years ago.
print("ax^2 + bx + c = d what is your values for them? ")
a = int(input(">a = "))
b = int(input(">b = "))
c = int(input(">c = "))
d = int(input(">d = "))
given_parabola = str(a) + "x^2 + " + str(b) + "x + " + (str(c)) + " = " + str(d)
Is there any other way that I can merge integer variables with strings?
The "best" approach really depends on what you're trying to do.
1. Concatenating lists with variable number of items (numbers and strings)
If you simply want to form a string from numbers and strings, I would first create a generator with generator expression and then join the strings with the join() method.
In [1]: a = [2, 'a', 3, 'x', 'foo', 8, 55]
In [2]: g = (str(x) for x in a)
In [3]: ' '.join(g)
Out[3]: '2 a 3 x foo 8 55'
Pluses
Can be used to concatenate any amount of strings and numbers, which can be in any order
Minuses
Probably not the most speed optimized, if you know more about the variables you are going to concatenate
2. Literal String interpolation
If you know what amount of numeric variables you want to concatenate with what strings, the problem is called string interpolation.
In Python 3.6+ you can use so-called f-strings to form string using a string template and a fixed number of variables. For example:
In [1]: a, b, c, d = 3, 2, 1, 5
In [2]: f"{a}x^2 + {b}x + {c} = {d}"
Out[2]: '3x^2 + 2x + 1 = 5'
Pluses
Probably the most speed optimized way to create a string from a template.
Minuses
This is not a general approach to "sum"/concatenate any amount of strings and numbers.
3. Using sympy for expression generation
Since your problem looks like being very specific: You want to create string from mathematical formula, you might want to look at sympy.
Installation
pip install sympy
Simple example
In [1]: from sympy import symbols, Eq, mathematica_code
In [2]: x, a, b, c, d = symbols('x a b c d')
In [3]: expr = Eq(a*(x**2) + b*x + c, d)
In [4]: var_dict = dict(a=3, b=2, c=1, d=5)
In [5]: expr_with_numbers = expr.subs(var_dict)
In [6]: mathematica_code(expr_with_numbers).replace('==', '=')
Out[6]: '3*x^2 + 2*x + 1 = 5'
you can also solve for the expression easily:
In [7]: solve(expr_with_numbers, x)
Out[7]: [-1/3 + sqrt(13)/3, -sqrt(13)/3 - 1/3]
and you can print any kind of equation. For example
In [1]: from sympy import symbols, Eq, mathematica_code, sqrt, pretty, solve
In [2]: expr = Eq(a*(x**2)/(sqrt(x-c)), d)
In [3]: var_dict = dict(a=3, b=2, c=1, d=5)
In [4]: expr_with_numbers = expr.subs(var_dict)
In [5]: print(pretty(expr_with_numbers, use_unicode=False))
2
3*x
--------- = 5
_______
\/ x - 1
Pros
Useful, if you want to create complex mathematical expressions
Can also output pretty multiline output or even LaTeX output.
Can be useful if you want to actually solve the equation, too
Cons
Not speed-optimized for simple string formation.
You can avoid concatenating multiple strings using the format string python proposed.
Using Format strings vs concatenation to do a list of more performant to less performant
f-string as f"{a}x^2 + {b}x + {c} = {d}"
"%sx^2 + %sx + %s = %s" % (a,b,c,d)
"{}x^2 + {}x + {} = {}".format(a,b,c,d)
Might I suggest string interpolation?
given_parabola = "%sx^2 + %sx + %s = %s" % (a, b, c, d)
Or
given_parabola = f"{a}x^2 + {b}x + {c} = {d}"
Yes, hopefully, this is what you mean:
# This way the integer 10 will convert to a string automatically. Works in Print as well!
x = 10
y = "lemons"
z = "In the basket are %s %s" % (x, y)
print(z)
Output:
In the basket are 10 lemons
I'm attempting to format numbers in scientific notation with exponents of base 10, e.g. write 0.00123 as 1.23x10–3, using python 3.
I found this great function which prints 1.23x10^-3, but how can the caret-exponent be replaced with a superscript?
def sci_notation(number, sig_fig=2):
ret_string = "{0:.{1:d}e}".format(number, sig_fig)
a,b = ret_string.split("e")
b = int(b) # removed leading "+" and strips leading zeros too.
return a + "x10^" + str(b)
print(sci_notation(0.001234, sig_fig=2)) # Outputs 1.23x10^-3
The function is modified from https://stackoverflow.com/a/29261252/8542513.
I've attempted to incorporate the answer from https://stackoverflow.com/a/8651690/8542513 to format the superscript, but I'm not sure how sympy works with variables:
from sympy import pretty_print as pp, latex
from sympy.abc import a, b, n
def sci_notation(number, sig_fig=2):
ret_string = "{0:.{1:d}e}".format(number, sig_fig)
a,b = ret_string.split("e")
b = int(b) #removed leading "+" and strips leading zeros too.
b = str(b)
expr = a + "x10"**b #Here's my problem
pp(expr) # default
pp(expr, use_unicode=True)
return latex(expr)
print(latex(sci_notation(0.001234, sig_fig=2)))
This returns: TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
Here's a simple solution:
def SuperScriptinate(number):
return number.replace('0','⁰').replace('1','¹').replace('2','²').replace('3','³').replace('4','⁴').replace('5','⁵').replace('6','⁶').replace('7','⁷').replace('8','⁸').replace('9','⁹').replace('-','⁻')
def sci_notation(number, sig_fig=2):
ret_string = "{0:.{1:d}e}".format(number, sig_fig)
a,b = ret_string.split("e")
b = int(b) # removed leading "+" and strips leading zeros too.
return a + "x10^" + SuperScriptinate(str(b))
I take it that your main problem is how can the caret-exponent be replaced with a superscript?
If you are using python in a Jupyter notebook, there is an easy way:
from IPython.display import display, Math, Latex
# if the number is in scientific format already
display(Math('2.14e-6'.replace('e', r'\times 10^{') + '}'))
# if it is not:
d = "%e" % (number)
# then use the above form: display(Math(d.replace('e', r'\times ...
The scinot package formats numbers in scientific notation
import scinot as sn
a=4.7e-8
print(scinot.format(a))
4.7 × 10⁻⁸
or in a string
print('The value is {0:s}'.format(scinot.format(a)))
The value is 4.7 × 10⁻⁸
I need to bruteforce some of the address space using python. At the moment this is my code:
offsets = [
"\x00","\x01","\x02","\x03","\x04","\x05","\x06","\x07","\x08","\x09","\x0a","\x0b","\x0c","\x0d","\x0e","\x0f"
,"\x10","\x11","\x12","\x13","\x14","\x15","\x16","\x17","\x18","\x19","\x1a","\x1b","\x1c","\x1d","\x1e","\x1f"
,"\x20","\x21","\x22","\x23","\x24","\x25","\x26","\x27","\x28","\x29","\x2a","\x2b","\x2c","\x2d","\x2e","\x2f"
,"\x30","\x31","\x32","\x33","\x34","\x35","\x36","\x37","\x38","\x39","\x3a","\x3b","\x3c","\x3d","\x3e","\x3f"
,"\x40","\x41","\x42","\x43","\x44","\x45","\x46","\x47","\x48","\x49","\x4a","\x4b","\x4c","\x4d","\x4e","\x4f"
,"\x50","\x51","\x52","\x53","\x54","\x55","\x56","\x57","\x58","\x59","\x5a","\x5b","\x5c","\x5d","\x5e","\x5f"
,"\x60","\x61","\x62","\x63","\x64","\x65","\x66","\x67","\x68","\x69","\x6a","\x6b","\x6c","\x6d","\x6e","\x6f"
,"\x70","\x71","\x72","\x73","\x74","\x75","\x76","\x77","\x78","\x79","\x7a","\x7b","\x7c","\x7d","\x7e","\x7f"
,"\x80","\x81","\x82","\x83","\x84","\x85","\x86","\x87","\x88","\x89","\x8a","\x8b","\x8c","\x8d","\x8e","\x8f"
,"\x90","\x91","\x92","\x93","\x94","\x95","\x96","\x97","\x98","\x99","\x9a","\x9b","\x9c","\x9d","\x9e","\x9f"
,"\xa0","\xa1","\xa2","\xa3","\xa4","\xa5","\xa6","\xa7","\xa8","\xa9","\xaa","\xab","\xac","\xad","\xae","\xaf"
,"\xb0","\xb1","\xb2","\xb3","\xb4","\xb5","\xb6","\xb7","\xb8","\xb9","\xba","\xbb","\xbc","\xbd","\xbe","\xbf"
,"\xc0","\xc1","\xc2","\xc3","\xc4","\xc5","\xc6","\xc7","\xc8","\xc9","\xca","\xcb","\xcc","\xcd","\xce","\xcf"
,"\xd0","\xd1","\xd2","\xd3","\xd4","\xd5","\xd6","\xd7","\xd8","\xd9","\xda","\xdb","\xdc","\xdd","\xde","\xdf"
,"\xe0","\xe1","\xe2","\xe3","\xe4","\xe5","\xe6","\xe7","\xe8","\xe9","\xea","\xeb","\xec","\xed","\xee","\xef"
,"\xf0","\xf1","\xf2","\xf3","\xf4","\xf5","\xf6","\xf7","\xf8","\xf9","\xfa","\xfb","\xfc","\xfd","\xfe","\xff"]
for i in xrange(110, 256):
num = offsets[i]
address = "\xee" + num + "\xff\xbf"
print `address`
And the output last part of the output:
'\xee\xfa\xff\xbf'
'\xee\xfb\xff\xbf'
'\xee\xfc\xff\xbf'
'\xee\xfd\xff\xbf'
'\xee\xfe\xff\xbf'
'\xee\xff\xff\xbf'
My question is if it is possible to get rid of the "offsets" array, and do it in a much cleaner way?
Sure is, just iterate over the xrange and call chr() on the current item:
>>> for i in xrange(110, 256):
... print "\xee" + chr(i) + "\xff\xbf"
Notice that it'll print the actual characters. If you just want to print the values, you can use the backticks, however a more pythonic approach is to use repr():
>>> for i in xrange(110, 256):
... print(repr("\xee" + chr(i) + "\xff\xbf"))
...
-- SNIP --
'\xee\xfa\xff\xbf'
'\xee\xfb\xff\xbf'
'\xee\xfc\xff\xbf'
'\xee\xfd\xff\xbf'
'\xee\xfe\xff\xbf'
'\xee\xff\xff\xbf'
for i in xrange(110, 256):
address = "\xee" + "\\" + hex(i)[1:] + "\xff\xbf"
print `address`
You can generate the offsets array in a one-liner:
offsets = ["0x{:02x}".format(_) for _ in range(0x100)]
You could just do the math, and let struct construct the 4-byte sequence.
base = b'\xee\x00\xff\xbf' #assuming little-endian for the math coming up
struct.unpack('I',base)
Out[89]: (3221160174,)
#showing they're the same, no magic involved
int('ee',16) + int('ff',16)*(16**4) + int('bf',16)*(16**6)
Out[90]: 3221160174
#equivalent to bitshifting, if you prefer
int('ee',16) + (int('ff',16) << 16) + (int('bf',16) << 24)
Out[91]: 3221160174
So that gives
start = 3221160174
[struct.pack('I', start + (x<<8)) for x in range(256)]
Out[93]:
[b'\xee\x00\xff\xbf',
b'\xee\x01\xff\xbf',
b'\xee\x02\xff\xbf',
b'\xee\x03\xff\xbf',
b'\xee\x04\xff\xbf',
b'\xee\x05\xff\xbf',
b'\xee\x06\xff\xbf',
#snip...
b'\xee\xff\xff\xbf']
I get this error when using a python script that calculates pi using the Gauss-Legendre algorithm. You can only use up to 1024 iterations before getting this:
C:\Users\myUsernameHere>python Desktop/piWriter.py
End iteration: 1025
Traceback (most recent call last):
File "Desktop/piWriter.py", line 15, in <module>
vars()['t' + str(sub)] = vars()['t' + str(i)] - vars()['p' + str(i)] * math.
pow((vars()['a' + str(i)] - vars()['a' + str(sub)]), 2)
OverflowError: long int too large to convert to float
Here is my code:
import math
a0 = 1
b0 = 1/math.sqrt(2)
t0 = .25
p0 = 1
finalIter = input('End iteration: ')
finalIter = int(finalIter)
for i in range(0, finalIter):
sub = i + 1
vars()['a' + str(sub)] = (vars()['a' + str(i)] + vars()['b' + str(i)])/ 2
vars()['b' + str(sub)] = math.sqrt((vars()['a' + str(i)] * vars()['b' + str(i)]))
vars()['t' + str(sub)] = vars()['t' + str(i)] - vars()['p' + str(i)] * math.pow((vars()['a' + str(i)] - vars()['a' + str(sub)]), 2)
vars()['p' + str(sub)] = 2 * vars()['p' + str(i)]
n = i
pi = math.pow((vars()['a' + str(n)] + vars()['b' + str(n)]), 2) / (4 * vars()['t' + str(n)])
print(pi)
Ideally, I want to be able to plug in a very large number as the iteration value and come back a while later to see the result.
Any help appreciated!
Thanks!
Floats can only represent numbers up to sys.float_info.max, or 1.7976931348623157e+308. Once you have an int with more than 308 digits (or so), you are stuck. Your iteration fails when p1024 has 309 digits:
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216L
You'll have to find a different algorithm for pi, one that doesn't require such large values.
Actually, you'll have to be careful with floats all around, since they are only approximations. If you modify your program to print the successive approximations of pi, it looks like this:
2.914213562373094923430016933707520365715026855468750000000000
3.140579250522168575088244324433617293834686279296875000000000
3.141592646213542838751209274050779640674591064453125000000000
3.141592653589794004176383168669417500495910644531250000000000
3.141592653589794004176383168669417500495910644531250000000000
3.141592653589794004176383168669417500495910644531250000000000
3.141592653589794004176383168669417500495910644531250000000000
In other words, after only 4 iterations, your approximation has stopped getting better. This is due to inaccuracies in the floats you are using, perhaps starting with 1/math.sqrt(2). Computing many digits of pi requires a very careful understanding of the numeric representation.
As noted in previous answer, the float type has an upper bound on number size. In typical implementations, sys.float_info.max is 1.7976931348623157e+308, which reflects the use of 10 bits plus sign for the exponent field in a 64-bit floating point number. (Note that 1024*math.log(2)/math.log(10) is about 308.2547155599.)
You can add another half dozen decades to the exponent size by using the Decimal number type. Here is an example (snipped from an ipython interpreter session):
In [48]: import decimal, math
In [49]: g=decimal.Decimal('1e12345')
In [50]: g.sqrt()
Out[50]: Decimal('3.162277660168379331998893544E+6172')
In [51]: math.sqrt(g)
Out[51]: inf
This illustrates that decimal's sqrt() function performs correctly with larger numbers than does math.sqrt().
As noted above, getting lots of digits is going to be tricky, but looking at all those vars hurts my eyes. So here's a version of your code after (1) replacing your use of vars with dictionaries, and (2) using ** instead of the math functions:
a, b, t, p = {}, {}, {}, {}
a[0] = 1
b[0] = 2**-0.5
t[0] = 0.25
p[0] = 1
finalIter = 4
for i in range(finalIter):
sub = i + 1
a[sub] = (a[i] + b[i]) / 2
b[sub] = (a[i] * b[i])**0.5
t[sub] = t[i] - p[i] * (a[i] - a[sub])**2
p[sub] = 2 * p[i]
n = i
pi_approx = (a[n] + b[n])**2 / (4 * t[n])
Instead of playing games with vars, I've used dictionaries to store the values (the link there is to the official Python tutorial) which makes your code much more readable. You can probably even see an optimization or two now.
As noted in the comments, you really don't need to store all the values, only the last, but I think it's more important that you see how to do things without dynamically creating variables. Instead of a dict, you could also have simply appended the values to a list, but lists are always zero-indexed and you can't easily "skip ahead" and set values at arbitrary indices. That can occasionally be confusing when working with algorithms, so let's start simple.
Anyway, the above gives me
>>> print(pi_approx)
3.141592653589794
>>> print(pi_approx-math.pi)
8.881784197001252e-16
A simple solution is to install and use the arbitrary-precisionmpmath module which now supports Python 3. However, since I completely agree with DSM that your use ofvars()to create variables on the fly is an undesirable way to implement the algorithm, I've based my answer on his rewrite of your code and [trivially] modified it to make use ofmpmath to do the calculations.
If you insist on usingvars(), you could probably do something similar -- although I suspect it might be more difficult and the result would definitely harder to read, understand, and modify.
from mpmath import mpf # arbitrary-precision float type
a, b, t, p = {}, {}, {}, {}
a[0] = mpf(1)
b[0] = mpf(2**-0.5)
t[0] = mpf(0.25)
p[0] = mpf(1)
finalIter = 10000
for i in range(finalIter):
sub = i + 1
a[sub] = (a[i] + b[i]) / 2
b[sub] = (a[i] * b[i])**0.5
t[sub] = t[i] - p[i] * (a[i] - a[sub])**2
p[sub] = 2 * p[i]
n = i
pi_approx = (a[n] + b[n])**2 / (4 * t[n])
print(pi_approx) # 3.14159265358979