How to print floating point in scientific format?

Alex Martelli aleax at aleax.it
Mon Aug 11 10:48:58 CEST 2003


sdhyok wrote:
   ...
>> I've never heard a scientific programmer complain too badly about
>> how Numeric treats arrays, whether they were coming from Fortran
>> (the typical case), other higher-level languages, or general purpose
>> languages not really suited for scientific computation (such as C).
> 
> Right, we can use scientific binary formats, like NetCDF, HDF.
> But, we often want to read the data in our naked eyes
> and exchange them with spreadsheet.

For "exchange with spreadsheets" see the csv module (new in 2.3), e.g.:

>>> import csv
>>> import sys
>>> csv.writer(sys.stdout).writerow([ 100.+i for i in range(3,8) ])
103.0,104.0,105.0,106.0,107.0
>>>

It doesn't, of course, force scientific format (it uses the general
format) -- spreadsheets don't need that.  However, it does have the
concept of a "Dialect" (here, I've let the dialect default to 'excel'),
a bundle of formatting parameters that tweak the output into the best
form for a given spreadsheet; that doesn't provide the specific bit
of formatting control you want, but it gives what's clearly the right
"hook" on which to hang any kind of formatting control.  If you need
to pursue "exchange with spreadsheet" and you have a use-case for
needing scientific format in such a setting, then proposing a patch
to module csv [having the dialect optionally record the preferred
way to format floating point numbers] might stand a good chance.

Right now, _csv.c [line 1126 in the sources) just transforms the
fields it's emitting with PyObject_Str(field) -- equivalent to the
Python call str(field), just as the print statement does.  But just
as it nows checks dialect->quoting before coming to that, it might
well check some other field of the '*dialect* structure in order
to influence output formatting selectively -- *IF* good use cases
could be found and verified where a spreadsheet's behavior can be
made better by special formatting of numbers fed to it.


>> You seem to be focused on readable display of arrays (quite an
>> unusual focus for scientific programming).  So, worst case, it's trivial
>> to write a general purpose function that takes an array of ANY size
>> and rank and emits it in the way you prefer -- easier than in any
>> other language commonly used for scientific programming.
>> 
>> So, you don't need anything from Python -- just write that blessed
>> function and scientifically program to your heart's content.
> 
> Trivial to create my own function.

We agree.

> But, surprisingly no common function or command for the work.

Actually, Numeric.array2string IS exactly such a "common function
or command".  It's been written 7 years ago by Konrad Hinsen and
happily used ever since by thousands of happy users of Numeric --
how much more common than this can you get?

However, among its very numerous formatting parameters, it does
NOT have one to let you force exponential format as opposed to
fixedpoint format -- it always decides that tidbit (i.e. whether
an 'e' or 'f' is ultimately used in the format string) by itself.

Clearly, no Numeric user has had substantial need for this kind
of forced output formatting over these many years -- which I do
not find at all surprising.  Still, array2string is a Python
coded function -- see its sources in Numeric/ArrayPrinter.py --
so that experimenting with changes to it is trivial, and maybe
the Numeric maintainers will look with favour upon a patch,
should you decide to offer one.  It might be as simple as adding
yet one more optional parameter to the array2string function,
say "forcedformat" defaulting to None, passing it on to the
underlying internal _floatFormat function it calls to determine
the format string, and having _floatFormat just use it, if not
None, instead of determining the format itself.  I would
suggest you make a copy of ArrayPrinter.py, tweak it to your
own satisfaction, then send the resulting patch to the Numeric
maintainers proposing inclusion in Numeric's next release.

> Maybe, one solution is
> 
> import Numeric as N
> N.print(array, format="%.2E")

In my opinion, the solution I just sketched for you, i.e.:

print N.array2string(array, precision=2, forcedformat="E")

stands a much better chance than the addition of a new function
that does direct printing (rather than the more useful and
flexibile formatting-to-string) and merges precision and
formatcharacter into one argument (note that array2string
does already accept a precision argument) -- even without
considering the fact that 'print' is a keyword and thus not
usable as a function-name.


Alex





More information about the Python-list mailing list