Is fortran-like print in python possible? - python

is it possible some way to "print" in python in a fortran like way like this?
1 4.5656
2 24.0900
3 698.2300
4 -3.5000
So the decimal points is always in the same column, and we get always 3 or n decimal numbers?
Thanks

>>> '%11.4f' % -3.5
' -3.5000'
or the new style formatting:
>>> '{:11.4f}'.format(-3.5)
' -3.5000'
more about format specifiers in the docs.

You could also take a look at the fortranformat library on PyPI or the project page if you wanted to fully recreate FORTRAN text IO.
If you have any questions, send me an email (I wrote it).

for i in [(3, 4.534), (3, 15.234325), (10,341.11)]:
... print "%5i %8.4f" % i
...
3 4.5340
3 15.2343
10 341.1100

print "%10.3f" % f
will right align the number f (as an aside: %-10.3f would be left-aligned). The string will be right-aligned to 10 characters (it doesn't work any more with > 10 characters) and exactly 3 decimal digits. So:
f = 698.230 # <-- 7 characters when printed with %10.3f
print "%10.3f" % f # <-- will print " 698.2300" (two spaces)
As a test for your example set do the following:
print "\n".join(map(lambda f: "%10.3f" % f, [4.5656, 24.09, 698.23, -3.5]))

You can use string.rjust(), this way:
a = 4.5656
b = 24.0900
c = 698.2300
d = -3.5000
a = "%.4f" % a
b = "%.4f" % b
c = "%.4f" % c
d = "%.4f" % d
l = max(len(a), len(b), len(c), len(d))
for i in [a, b, c, d]:
print i.rjust(l+2)
Which gives:
~ $ python test.py
4.5656
24.0900
698.2300
-3.5000

Fortran io is totally different to C style io in every way.
Go for Brendan's fortranformat package.
https://pypi.python.org/pypi/fortranformat
easy_install fortranformat
This allows arcane old fortran input files to be created with much less trial and error than trying to use C style string formatting.

Related

Sympy: How can I store an equation in order to solve it later numerically?

Hello wonderful people,
I am building a physics model for some project. I have found a nice equation for my interest variable, but I would like to be able to solve the problem repeatedly with different parameters. What I would like to do is to save my equation as an object in a file (using pickle for example), then loading it at runtime and feed it the parameters it needs.
How would you achieve this?
With a simple example, the whole process would look like this:
(in a jupyter notebook)
import sympy as sp
import pickle
a, b, c = symbols("a b c")
eqn = sp.Eq(b + c, a) #for a real equation I would simplify it before using sympy
with open("eqn.txt") as f:
pickle.dump(eqn, f)
and then later in the app's code:
...
with open("eqn.txt") as f:
eqn = pickle.load(f)
b = 1
c = 2
#magic line to put b and c into the equation
a = sp.solve(eqn, a)
print(a) # 3
Implementing the whole equation directly in a function is probably not an option although I am considering how to implement it manually. It just looks really, really hard to do and if I could do it in two lines using simpy, that'd be great.
Thanks for your time!
with open("eqn.txt") as f:
eqn = pickle.load(f)
b, c = 1, 2 # b,c are python symbols here
reps = dict(zip(symbols('b c'), (b, c))) # keys are SymPy Symbols, values are 1,2
eqn = eqn.xreplace(reps) #magic line to put b and c into the equation
a = sp.solve(eqn, a)
print(a) # 3
It is important to keep in mind the distinction between b = 1 and b = Symbol('b'). The left hand side of the expressions are Python variables and on the right, an int or a SymPy Symbol, respectively. In a SymPy expression you might reference a Python variable and its value will be included in the equation:
>>> from sympy import *
>>> b = 1
>>> b + 1
2
>>> b = Symbol('b')
>>> b + 1
b + 1
>>> eq = _
>>> eq.subs(b,1)
2
>>> b=2 # assigning a new value to b does not change the object in eq
>>> eq
b + 1
>>> eq.subs(b, 2) # i.e., eq.subs(2,2) doesn't work -- no 2 in eq
b + 1
>>> eq.subs(Symbol('b'), 2) # replace the Symbol with value of 2 works
3
So in reps above, zipping the symbols to their corresponding values creates a mapping that can be used to do the replacement.
There is more discussion of such issues in the documentation gotchas file, but this should help with your current issue.

Integer from tuple, divided, yields integer instead of float?

In the code below,
abc = (1,2,3)
a = abc[0]
b = abc[1]
c = abc[2]
print('%d, %d, %d' %(a,b,c)) # gives 1,2,3 as expected
a /= 3
b /= 3
c /= 3
print('%d, %d, %d' %(a,b,c)) # gives 0,0,1... which is NOT expected
I'm trying, however, to have a, b, c be 0.333, 0.6666, 1 respectively.
This problem persists even when I:
divide by 3.0
use a stupid abc = tuple([i/3.0 for i in abc]) workaround and then try to list all the elements again as above
even when I cast everything into a float like:
a = float(float(a)/float(3.0)) # still returns 0
I'm even using python 3, so an int/int division should return a float regardless.
Your print statements say to display the values as integers (%d); try using %f instead.
You are using %d so the output is printed as ints/decimal just use print:
print(a,b,c)
Use %f inside print statement
print('%f, %f, %f', %(a,b,c))

The for loop with letters instead of numbers

i know the for loop:
for i range(2, 6):
print i
gives this output:
2
3
4
5
can i also do this somehow with letters?
for example:
# an example for what i'm looking for
for i in range(c, h):
print i
c
d
f
g
I think it's nicer to add 1 to ord('g') than using ord('h')
for code in range(ord('c'), ord('g') + 1):
print chr(code)
because what if you want to go to 'z', you need to know what follows 'z' . I bet you can type + 1 faster than you can look it up.
for i in 'cdefg':
...
for i in (chr(x) for x in range(ord('c'), ord('h'))):
This also works, this way its very explicit what you are working with:
import string
s = string.ascii_lowercase
for i in s[s.index('c'):s.index('h')]:
print i
There's no reason not to use:
>>> for char in "cdefg":
... print(char)
c
d
e
f
g
Even if you weren't a programmer, you could figure out what the loop does, it's basically English.
It's also much cleaner, it's shorter, and the best part is that it's 6 times faster than the chr(ord()) solution:
>>> import timeit
>>> timeit.timeit("for i in 'abcdefg': x = i")
0.27417739599968627
>>> timeit.timeit("for i in range(ord('a'), ord('g') + 1): x = chr(i)")
1.7386019650002709
How about this?
for code in range(ord('c'), ord('h')):
print chr(code)

Creating fibonacci sequence generator (Beginner Python)

Hi I'm trying to create a Fibonacci sequence generator in Python. This is my code:
d =raw_input("How many numbers would you like to display")
a = 1
b = 1
print a
print b
for d in range(d):
c = a + b
print c
a = b
b = c
When I ran this program, I get the error:
File "Fibonacci Sequence Gen.py", line 10, in <module>
for d in range(d):
TypeError: range() integer end argument expected, got str
Thanks for your help, I'm trying to teach myself python with basic projects.
raw_input returns a string. So convert d to an integer with:
d = int(d)
One more thing: Do not use for d in range(d). It works but it is awful, unpythonic, whatever.
Try this way for example:
numbers = raw_input("How many numbers would you like to display")
a = 1
b = 1
print a
print b
for d in range(int(numbers)):
c = a + b
print c
a = b
b = c
Edit: I complete below the answer with additional code tuning (thanks to commenters):
# one space will separate better visually question and entry in console
numbers = raw_input("How many numbers would you like to display > ")
# I personnally prefer this here, although you could put it
# as above as `range(int(numbers))` or in `int(raw_input())`
# In a robust program you should use try/except to catch wrong entries
# Note the number you enter should be > 2: you print 0,1 by default
numbers = int(numbers)
a, b = 0, 1 # tuple assignation
# note fibonnaci is 0,1,1,2,3...
print a # you can write this as print "%i\n%i" % (a, b)
print b # but I think several prints look better in this particular case.
for d in range(numbers - 2): # you already printed 2 numbers, now print 2 less
c = a + b
print c
a, b = b, c # value swapping.
# A sorter alternative for this three lines would be:
# `a, b = b, a + b`
# `print b`
Problem
The problem here is that here:
d = raw_input("How many numbers would you like to display")
you assign string from the input into the d variable, and later you pass it to range(). But range() expects expects integers, not strings, and Python does not convert it automatically (it leaves conversion to you).
Solution
The solution is to convert result of raw_input() into int like that:
d = int(raw_input("How many numbers would you like to display"))
and everything will work unless you provide non-integer.
But there is better (shorter, more efficient, more encapsulated) method of generating Fibonacci numbers (see below).
Better method of generating Fibonacci numbers
I believe this is the best (or nearly the best) solution:
def fibo(n):
a, b = 0, 1
for i in xrange(n):
yield a
a, b = b, a + b
This is a generator, not a simple function. It is very efficient, its code is short and does not print anything, but you can print its result like that:
>>> for i in fibo(20):
print i,
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
or convert it into a list like that:
>>> list(fibo(20))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
Applying the above in your case
After applying the above to your code, it could look like this:
def fibo(n):
a, b = 0, 1
for i in xrange(n):
yield a
a, b = b, a + b
d = int(raw_input("How many numbers would you like to display"))
for i in fibo(d):
print i
Does it answer your question?
You have to convert the input to a number, like this:
d = int(raw_input("How many numbers would you like to display: "))
Also, just for fun, the fibonacci sequence can be expressed more succinctly:
a, b = 0, 1
for i in range(d):
print a
a, b = b, a+b
raw_input returns string type.You need to convert it to int.
>>> x = raw_input()
2
>>> x
'2'
>>> type(x)
<type 'str'>
and range function requires int as an argument not string.
Thats why when i do
>>> range(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: range() integer end argument expected, got str.
So, change it to
for x in range(int(d)):
Simpler method:
a = [0,1]
for n in range(1,41):
a.append(a[n]+a[n-1])
print a[-1]
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
46368
75025
121393
196418
317811
514229
832040
1346269
2178309
3524578
5702887
9227465
14930352
24157817
39088169
63245986
102334155
165580141
I see many over complicated Fibonacci Sequence programs so I just did this with a while loop; changing the number after the while loop
a = 0
b = 1
while a <= 1000000000: #Changing this number will change how long the sequence goes on for
print(a)
print(b)
a = a+b
b = b+a
I know this isn't your program but it is a very basic version;
I hope this helps :)

How to right-align numeric data?

I have some data that I am displaying in 3 column format, of the form:
key: value key: <tab> key: value <tab> key: value.
Here's an example:
p: 1 sl: 10 afy: 4
q: 12 lg: 10 kla: 3
r: 0 kl: 10 klw: 3
s: 67 vw: 9 jes: 3
t: 16 uw: 9 skw: 3
u: 47 ug: 9 mjl: 3
v: 37 mj: 8 lza: 3
w: 119 fv: 8 fxg: 3
x: 16 fl: 8 aew: 3
However, I'd like if the numbers were all right aligned, such as:
a: 1
b: 12
c: 123
How can I do this in Python?
Here is the existing printing code I have:
print(str(chr(i+ord('a'))) + ": " + str(singleArray[i]) + "\t" +
str(doubleArray[i][0]) + ": " + str(doubleArray[i][1]) + "\t" +
str(tripleArray[i][0]) + ": " + str(tripleArray[i][1]))
In python 2.6+ (and it's the standard method in 3), the "preferred" method for string formatting is to use string.format() (the complete docs for which can be found here).
right justification can be done with
"a string {0:>5}".format(foo)
this will use 5 places, however
"a string {0:>{1}}".format(foo, width)
is also valid and will use the value width as passed to .format().
In Python 2.5 use rjust (on strings). Also, try to get used to string formatting in python instead of just concatenating strings. Simple example for rjust and string formatting below:
width = 10
str_number = str(ord('a'))
print 'a%s' % (str_number.rjust(width))
Use python string formatting: '%widths' where width is an integer
>>> '%10s' % 10
' 10'
>>> '%10s' % 100000
' 100000'
In Python 3.6 you can use Literal String
Interpolation, which is less
verbose and probably more intuitive to use:
width = 5
number = 123
print (f'{number:>{width}}')
Or just:
number = 123
print (f'{number:>5}')
It reuses much of the str.format() syntax.
I guess/hope this will be the prefered way in the future.
If you know aa upper bound for your numbers, you can format with "%<lenght>d" % n. Given all those calculations are done and in a list of (char, num):
mapping = ((chr(i+ord('a')), singleArray[i]),
(doubleArray[i][0],doubleArray[i][1]),
(tripleArray[i][0],tripleArray[i][1])
)
for row in mapping:
print "%s: %3d" % row

Categories

Resources