Ask Your Question

Revision history [back]

At the beginning of your function, add a line to test if x is integer. Optionally, add a test of how large this integer is if you still want to put large integers in scientific notation.

Optionally, you can also test whether x is a floating-point number equal to zero, in which case you might not want to put it in scientific notation.

Then, you can reduce the number of digits by taking x.n(digits=4) (this will also turn an integer into a floating-point number, which you may want to do for large integers).

You can then apply the method str with the option no_sci=False to make sure to get a scientific notation regardless of the size of x. The method also has an option skip_zeroes. Learn more about this method by reading the documentation:

x = 1.2
x.str?

Combining these tricks, your function could look like this:

def numprint(x):
    if type(x) == sage.rings.integer.Integer or type(x) == int:
        if abs(x) < 1000: return sage.misc.latex.LatexExpr(x)
    if x == 0.: return LatexExpr('0.')
    s = x.n(digits=4).str(no_sci=False).split('e')
    s = s[0].replace('.', r',\!') + r' \,\ldotp 10^{' + s[1] + '}'
    return sage.misc.latex.LatexExpr(s)

I would suggest to check carefully if the output is what you hoped for each in a wide variety of inputs.

z = dict()
z[1] = [0, 1, 100, 1000, 10000, 100000, 10000000000000000000]
z[2] = [12, 123, 1234, 12345, 1234567890, 12345678901234567890]
z[3] = [0., 1., 100., 1000., 10000., 100000., 10000000000000000000.]
z[4] = [12., 123., 1234., 12345., 1234567890., 1234567890123456.]
z[5] = [0.00012, 0.12, 1.2, 1.23, 1.234, 1.23456, 1.2345678]
z[6] = [0.00012345678, 1.2345678, 12.345678, 1234.5678, 1234567.8]
z[7] = [1.2345e-2, 1.2345e-1, 1.2345e0, 1.2345e1, 1.2345e3, 1.2345e5]

for a in z:
   print '----- test', a, '-----'
   for x in z[a]:
       print '%30s%30s'%(x,numprint(x))
   print ''

Having a wide range of different inputs to test is good when you are adjusting your function. Add special cases as needed.