问题
A different exercise. This one asked to evaluate the value of x for x-2=ln(x). There are two approaches (A and B) - one makes use of the given equation and yields the smaller solution (x1). The other approach uses e**(x-2)=x and yields the other solution (x2).
Program plots the graphical solution and then queries for initial value input. Then it evaluates x using appropriate approaches. Approach A requires initial condition lesser than x2, approach B requires initial condition greater than x1. Both approaches work for initial conditions that lay somewhere between x1 and x2.
The last part of the code manipulates the output to print only unique solutions.
# imports necessary modules
import matplotlib.pyplot as plt
import numpy as np
# plots the equation to provide insight into possible solutions
p = []
x = np.arange(0,5,0.01)
f = x - 2
g = np.log(x)
plt.plot(x,f)
plt.plot(x,g)
plt.show()
# x - 2 = ln(x)
print
lista = map(float, raw_input("Provide the starting conditions to establish the approximate value of the solutions to x-2=ln(x) (separate with spacebar): ").split(" "))
print
sigdig = int(raw_input("Define the number of significant digits (up to 15): "))
print
results1 = []
results2 = []
results3 = []
results4 = []
results = []
resu = []
for i in lista:
if i > 0.1586:
y = i
left = y - 2
right = np.log(y)
expo = "%d" % sigdig
epsi = 10**(-int(expo)-1)
step = 0
while abs(left - right) > epsi:
y = right + 2
right = np.log(y)
left = y - 2
step += 1
results1.append(y)
results2.append(results1[-1])
if i < 3.1462:
z = i
left = np.e ** (z - 2)
right = z
expo = "%d" % sigdig
epsi = 10**(-int(expo)-1)
step = 0
while abs(left - right) > epsi:
z = np.e ** (right - 2)
left = np.e ** (z - 2)
right = z
step += 1
results3.append(z)
results4.append(results3[-1])
# combines and evaluates the results
results = results2 + results4
for i in range(len(results)):
if round(results[i], sigdig) not in resu:
resu.append(round(results[i], sigdig))
else:
pass
print "For given starting conditions following solutions were found:"
print
for i in range(len(resu)):
printer = '"x_%d = %.' + str(sigdig) + 'f" % (i+1, resu[i])'
print eval(printer)
My questions are: is it possible to feed the approximate values of x1 and x2 (lines 36 and 53) from the graphical solution instead of hard coding them? Is possible to enforce the number of decimals without the eval work-around present in the code? Printing resu[i] normally yields results that end before nearest decimal "0" (near the end of code). Thanks.
回答1:
You can use *
in python format strings in a similar fashion to C/C++. When the %
operator encounters a *
in the format string, it looks for an integar in the list and uses it as if it were a constant in the format string.
The following should work for what you are trying to do:
print "x_%d = %.*f" % (sigdig,sigdig,resu[i])
If result
is 1.23456
and sigdig
is 3
, this will output:
x_3 = 1.234
Note that python floats are IEEE794 double precision values, which means they have about 15 significant digits. For example:
>>> print "x_%d = %.*f" % (30,30,1.0/3.0)
x_30 = 0.333333333333333314829616256247
Note how everything beyond the 17th decimal is essentially random garbage.
回答2:
I thought your question, https://stackoverflow.com/questions/15709496 (now closed), was really interesting. It was a shame to see it closed so, I am going to continue with this as an exercise, and post it on the following blog: http://nickburns2013.wordpress.com/2013/04/01/3d-water-model/. Feel free to comment / add bits and pieces.
This is completely unrelated to this question here. Apologies to anyone who is following this thread.
来源:https://stackoverflow.com/questions/15177354/enforcing-the-number-of-decimal-places-when-printing-results