Python - Rounding to two specific digits EXACTLY - python-2.7

The number I have = 52.003
The number I want = 52.00
The number I get after rounding to 2 decimal places:
round(52.003, 2)
>>> 52.0
How do I keep the second digit without Python automatically rounding it?

You can use the format() function in Python.
"{0:.2f}".format(round(52.003, 2))
You can also use the string formatting operator.
'%.2f' % 52.003

You can modify the output format like this:
a = 52.003
print "%.2f" % a

Try this function :
import numpy as np
Round = lambda x, n: eval('"%.' + str(int(n)) + 'f" % ' + repr(x))
a = Round(52.003,2)
print a
>>> 52.00
Just indicate the number of decimals you want as a kwarg. However the result will be a string.

Related

How to round specific parts of symbolic expression using sympy?

I'm new to python and sympy and am a little lost. What's the easiest way to round all of the numbers except 0.268994781998603, 0.525103332486078, and 0.2357023740927390 in equations that look like this:
0.268994781998603*x**0.24883285 + 0.525103332486078*exp(-Abs(2.011218*x - 1.101318)) + 0.2357023740927390*x**0.25234357
Would it have to do with using srepr?
Ultimately, I'd like to round the exponents 0.24883285 and 0.25234357 to .25 so sympy will combine those respective terms when using sympify.
Thanks!
It looks like what you want to do is keep the high precision Float but round the lower precision ones. You can discriminated based on the associated precision. I defined 'eq' to be the equation you gave above:
>>> for i in sorted(eq.atoms(Float)):
... print(i._prec, i)
...
27 -1.101318
53 0.235702374092739
30 0.24883285
30 0.25234357
53 0.268994781998603
53 0.525103332486078
27 2.011218
So let's get the lower precision floats in a list:
>>> lp = [i for i in eq.atoms(Float) if i._prec <= 30]
And let's define a replacement dictionary that rounds to two decimal places:
>>> reps = {k: k.round(2) for k in lp}
And now use it to replace those Floats in eq
>>> eq.subs(reps)
>>> eq.subs(reps)
0.504697156091342*x**0.25 + 0.525103332486078*exp(-Abs(2.01*x - 1.1))
The exponents, now being the same, caused the two terms to join.
If you rounded at two significant figures you would get:
>>> reps = {k: k.n(2) for k in lp}
>>> eq.subs(reps)
0.268994781998603*x**0.25 + 0.235702374092739*x**0.25 + 0.525103332486078*exp(-Abs(2.0*x - 1.1))
The terms don't join because these 2-sig-fig values are not exactly the same. Conversion to a string and re-sympification will work, however. (But I would stick to the round version.)
>>> eq2 = _
>>> from sympy import S
>>> S(str(eq2))
0.504697156091342*x**0.25 + 0.525103332486078*exp(-Abs(2.0*x - 1.1))
To just replace Floats in a given region of the expression there are lots of ways to parse up the expression: coefficients of Mul, constant terms of Add, etc... In the comments below you say that you want to make the change in sin, sign, exp and exponents (Pow) so something like this can work:
>>> from sympy import sin, sign, exp, Pow
>>> eq.replace(
... lambda x: isinstance(x, (sin, sign, exp, Pow)),
... lambda x: x.xreplace(dict([(i,i.round(2)) for i in x.atoms(Float)])))
0.504697156091342*x**0.25 + 0.525103332486078*exp(-Abs(2.01*x - 1.1))

Python code to convert decimal to binary

I need to write a Python script that will convert and number x in base 10 to binary with up to n values after the decimal point. And I can't just use bin(x)! Here's what I have:
def decimal_to_binary(x, n):
x = float(x)
test_str = str(x)
dec_at = test_str.find('.')
#This section will work with numbers in front of the decimal
p=0
binary_equivalent = [0]
c=0
for m in range(0,100):
if 2**m <= int(test_str[0:dec_at]):
c += 1
else:
break
for i in range(c, -1, -1):
if 2**i + p <= (int(test_str[0:dec_at])):
binary_equivalent.append(1)
p = p + 2**i
else:
binary_equivalent.append(0)
binary_equivalent.append('.')
#This section will work with numbers after the decimal
q=0
for j in range(-1, -n-1, -1):
if 2**j + q <= (int(test_str[dec_at+1:])):
binary_equivalent.append(1)
q = q + 2**j
else:
binary_equivalent.append(0)
print float((''.join(map(str, binary_equivalent))))
So say you call the function by decimal_to_binary(123.456, 4) it should convert 123.456 to binary with 4 places after the decimal, yielding 1111011.0111.
The first portion is fine - it will take the numbers in front of the decimal, in this case 123, and convert it to binary, outputting 1111011
However, the second portion, which deals with values after the decimal, is not doing what I think it should. The output it gives is not .0111, but rather .1111
I ran through the code with pen and paper writing down the value for each variable and it should work. But it doesn't. Can anyone help me fix this?
I call the function as decimal_to_binary(123.456, 4) and it prints out 1111011.1111
You're close, but there's an issue with your comparison when you go beyond the decimal:
if 2**j + q <= (int(test_str[dec_at+1:])):
What you're doing here is comparing a fractional value (since j is always negative) to a whole integer value. This comparison will, for all practical purposes, always be true.
Based on the surrounding logic, my guess would be that you're attempting to compare it to the actual decimal value here. Using your data, that would be 0.4 on the first iteration, so you expect the statement to be evaluated as:
0.5 <= 0.4
The actual comparison in your code is:
0.5 <= 4
There are two separate issues here:
You're taking all of the numbers after the decimal point, but not actually including the decimal point itself in your extraction. This is primarily why you are getting whole numbers in your test incorrectly. This is fixed simply by referencing test_str[dec_at:] rather than test_str[dec_at+1:]
You're casting to int. Even if you applied the change in the first point, your code would still not run correctly. However, in that case it would be because the cast would truncate the value down to 0 on every iteration. Cast to a float instead: float(test_str[dec_at:])
Your comparison line thus becomes if 2**j + q <= (float(test_str[dec_at:])):, which provides the correct output on my machine.
Note that floating point comparisons can be "finicky" in some situations, depending on rounding and the like. There are ways to mitigate this if needed.

Python arithmetic operation returns 0

read = True
while read:
my_input = int(raw_input())
print my_input
result = (1/6) * my_input * (my_input + 1) * (my_input +2)
if result == 0:
print ''
read = False
break
else:
print result
I wrote this little code snippet to solve 1 + (1+2) + (1+2+3+)... without looping over anything but the result is always 0 for some reason. I am using PyDev on Eclipse but I do not think that's even remotely the issue
Thank you
Multiplying by zero always results in zero.
>>> a = (1/6)
>>> print a
0
This is happening because Python is casting the resulting operation to integer.
In order to get a float result you can specify the values in decimal notation.
>>> a = 1.0/6.0
>>> print a
0.166666666667
Integer division.
When you divide (1/6) it comes out to 0 because of integer division.
When two ints are divided, they come out to the normal answer, minus anything after the decimal point.
For example, 1/4 would usually equal 0.25.
However, everything after the decimal point is dropped, so it comes out to 0.

Float to Scientific notation [duplicate]

I want to have Python2.7 print out floating point numbers in scientific notation, forced to start with 0. For instance, assume
a=1234567890e12
print '{:22.16E}'.format(a)
1.2345678900000000E+21
However, I want a print output that looks like:
0.1234567890000000E+22
Notice that the exponent is raised by one since the desired output is forced to a leading zero. How can I achieve this?
Thanks.
The fortranformat package will do what you are looking for.
import fortranformat as ff
a=1234567890e12
lineformat = ff.FortranRecordWriter('(1E26.16)')
lineformat.write([a])
Output:
' 0.1234567890000000E+22'
Handles E- as well.
def fortranFormat(n):
a = '{:.4E}'.format(float(n))
e = a.find('E')
return '0.{}{}{}{:02d}'.format(a[0],a[2:e],a[e:e+2],abs(int(a[e+1:])*1+1))
print(fortranFormat('60.505'))
print(fortranFormat('74.705'))
print(fortranFormat('2.000000E-09'))
output:
0.60505E+02
0.74705E+02
0.20000E-08
Well, since what you want to do is not "standard" scientific notation, I'm not sure if there is a simple call to do this. Here is a hack, however, that will work
a = 1234567890e12
A = str(a)
exp = A.find('e+')
converted = '0.' + A[0] + A[2:exp] + 'e+' + str(int(A[exp+2:])+1)

Rounding Decimal to configurable decimal places in python

Is there a better (faster, more efficient, or "just more pythonic") way than my way in rounding Decimals in Python? I came up with the following:
sign, digits, exponent = the_number.as_tuple()
Decimal((sign, digits[:exponent+len(digits)+decimal_places],-decimal_places))
edit:
I ended up using yet another solution that is faster[1] and also "fills" the decimal to the wanted precision:
decimal.Decimal('%.*f' % (decimal_places, number))
[1] It is faster up to ~200 decimal places. In my case I get a random float-value I want to "cast" to decimal, so the original precision is already limited and << 200.
What about round (builtin):
>>> the_number = decimal.Decimal(1.23456789)
>>> round(the_number, 2)
Decimal('1.23')
>>> d=decimal.Decimal("31.100")
>>> d
Decimal('31.100')
>>> round(d, 10)
Decimal('31.1000000000')
>>> round(d, 20)
Decimal('31.10000000000000000000')
>>> round(d, 24)
Decimal('31.100000000000000000000000')
>>> round(d, 26)
Decimal('31.10000000000000000000000000')
>>> round(d, 1)
Decimal('31.1')
>>> round(d, 0)
Decimal('31')
May try:
with decimal.localcontext() as ctx:
ctx.prec = aWantedPRECISION # temporarily adapt precision to aWantedPRECISION
result = +the_number # set
if this is Pythonic-enough