Question

I often use the python interpreter for doing quick numerical calculations and would like all numerical results to be automatically printed using, e.g., exponential notation. Is there a way to set this for the entire session?

For example, I want:

>>> 1.e12
1.0e+12

not:

>>> 1.e12
1000000000000.0
Was it helpful?

Solution

Create a Python script called whatever you want (say mystartup.py) and then set an environment variable PYTHONSTARTUP to the path of this script. Python will then load this script on startup of an interactive session (but not when running scripts). In this script, define a function similar to this:

def _(v):
    if type(v) == type(0.0):
        print "%e" % v
    else:
        print v

Then, in an interactive session:

C:\temp>set PYTHONSTARTUP=mystartup.py

C:\temp>python
ActivePython 2.5.2.2 (ActiveState Software Inc.) based on
Python 2.5.2 (r252:60911, Mar 27 2008, 17:57:18) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> _(1e12)
1.000000e+012
>>> _(14)
14
>>> _(14.0)
1.400000e+001
>>>

Of course, you can define the function to be called whaetver you want and to work exactly however you want.

Even better than this would be to use IPython. It's great, and you can set the number formatting how you want by using result_display.when_type(some_type)(my_print_func) (see the IPython site or search for more details on how to use this).

OTHER TIPS

Hm... It's not a 100% solution, but this have come to my mind...

How about defining a subclass of float which would have an overridden __str__ method (to print with the exp notation). And then you would have to wrap all the expressions with object construction of this class). It would be a bit shorter than Dave's solution, you would define the class once and then write something like:

>>> F(1.e12)
1.0e+12
>>> F(3.)
3.0e+0
>>> F(1.+2.+3.+4.)
1.0e+1
...

As you know you can use the % operator or str.format to format strings:

For example:

>>> "%e" % 1.e12
'1.000000e+12'

I was wondering if you could monkey patch the built-in float class to change the formatting but it seems that Python won't let you:

>>> 1.e12.__class__.__repr__ = lambda x: "%e" % x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'float'

So the only other thing I can think of is to write your own file-like object which captures output, reformats it and sends it to the standard output. You'd then redirect standard output of the interpreter to this object:

sys.stdout = my_formatting_object

Building on Dave Webb's hint above. You can of course set the precision if you like ("%.3e") and perhaps override writelines if needed.

import os
import sys

class ExpFloatFileObject:
    def write(self, s):
        try:
            s = "%e"%float(s)
        except ValueError:
            pass
        sys.__stdout__.write(s)

    def __getattr__(self, name):
        return getattr(sys.__stdout__, name)

sys.stdout = ExpFloatFileObject()  

and usage:

>>> 14000    
1.400000e+04  
>>> "text"
'text'

When using IPython/Jupyter-console, the "magic" command %precision %e will change the display of raw floats in exponential notation. https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-precision

For more formatting control, a formatter can be registered:

excited_floats = lambda val: "{:e}!!!".format(val)
console_formatter = get_ipython().display_formatter.formatters['text/plain']
console_formatter.for_type(float, lambda val, p, c: p.text(excited_floats(val)))

https://ipython.readthedocs.io/en/stable/api/generated/IPython.core.formatters.html#IPython.core.formatters.PlainTextFormatter

Sorry for necroposting, but this topic shows up in related google searches and I believe a satisfactory answer is missing here.

I believe the right way is to use sys.displayhook. For example, you could add code like this in your PYTHONSTARTUP file:

import builtins
import sys
import numbers


__orig_hook = sys.displayhook

def __displayhook(value):
    if isinstance(value, numbers.Number) and value >= 1e5:
        builtins._ = value
        print("{:e}".format(value))
    else:
        __orig_hook(value)

sys.displayhook = __displayhook

This will display large enough values using the exp syntax. Feel free to modify the threshold as you see fit.

Alternatively you can have the answer printed in both formats for large numbers:

def __displayhook(value):
    __orig_hook(value)
    if isinstance(value, numbers.Number) and value >= 1e5:
        print("{:e}".format(value))

Or you can define yourself another answer variable besides the default _, such as __ (such creativity, I know):

builtins.__ = None
__orig_hook = sys.displayhook

def __displayhook(value):
    if isinstance(value, numbers.Number):
        builtins.__ = "{:e}".format(value)
    __orig_hook(value)

sys.displayhook = __displayhook

... and then display the exp-formatted answer by typing just __.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top