Rounding Decimal to configurable decimal places in python - python-2.7

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

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))

How to get a floating point in Python? [duplicate]

This question already has answers here:
How can I force division to be floating point? Division keeps rounding down to 0?
(11 answers)
Closed 4 years ago.
In following code, I always get the result as a closest integer. But I would like to have the result of the division as a float i.e. 12/5 = 1.4, not 2 which is what I get in the program. I am using python2.7
"""Given division of two numbers, the result will print out """
try:
divident = int(raw_input("Enter the divident: "))
divisor = int(raw_input("Enter the divisor: "))
print (" %d devided by %d is %f: " % ( divident, divisor, divident / divisor))
except(ValueError, ZeroDivisionError):
print ("Something went wrong!")
The basic explanation is that in almost all programming languages, dividing 2 variables of numeric type T returns a value of that type T.
Integers division is performed by the processor as an euclidian division, returning the quotient (as an integer).
The print format %f will not perform the variable type conversion for you.
I strongly suggest you read the proposed duplicate question for further understanding of python behaviour.
Example:
12 = (2 * 5) + 2 => 12 / 5 = 2 12 % 5 = 2
12 = (1 * 7) + 5 => 12 / 7 = 1 12 % 7 = 5
In python :
Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 12/5
2
>>> 12%5
2
>>> 12/7
1
>>> 12%7
5
if you want to obtain a float, do as https://stackoverflow.com/users/8569905/banghua-zhao proposed.
cast in float, and then perform a division. The processor will then using floating point division and return a float.
As pointed out in a comment below, if 2 operands have a different type, the operator computation is performed with the most restrictive type : float will take precedence over integer. In the following examples, one cast to float would be sufficient.
>>> float(12)/float(5)
2.4
Note that the % operator still performs an euclidian divison and gives you a the result as a float
>>> float(12)%float(5)
2.0
>>> float(12)%float(7)
5.0
You divident and divisor are int type since you use int() method to convert the value from raw_input() into int type.
As a result, divident / divisor is also an int type. You need to convert int to float (for example: float()) before division.
"""Given division of two numbers, the result will print out """
try:
divident = int(raw_input("Enter the divident: "))
divisor = int(raw_input("Enter the divisor: "))
print (" %d devided by %d is %f: " % ( divident, divisor, float(divident) / float(divisor)))
except(ValueError, ZeroDivisionError):
print ("Something went wrong!")
Output:
Enter the divident: 12
Enter the divisor: 5
12 devided by 5 is 2.400000:
Note, if your inputs are not integers, consider converting them to float at the begining:
divident = float(raw_input("Enter the divident: "))
divisor = float(raw_input("Enter the divisor: "))
You must declare the input type as float in place of int because the input type determines the output type.
You should try:
a=float(input('your prompt string'))
b=float(input('your 2nd prompt'))
print(a/b)

Python - Rounding to two specific digits EXACTLY

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.

Mod function fails in python for large numbers

This python code
for x in range(20, 50):
print(x,math.factorial(x),math.pow(2,x), math.factorial(x) % math.pow(2,x) )
calculates fine up to x=22 but the mod when x>22 is always 0.
Wolframalpha says the results for x>22 are nonzero.
For example, when x=23 we get 6815744.
I guess this problem results from how python actually calculates the mod function but was wondering if anyone actually knew.
You are running into floating point limitations; math.pow() returns a floating point number, so both operands are coerced to floats. For x = 23, math.factorial(x) returns an integer larger than what a float can model:
>>> math.factorial(23)
25852016738884976640000
>>> float(math.factorial(23))
2.585201673888498e+22
The right-hand-side operator is a much smaller floating point number (only 7 digits), it is that difference in exponents that causes the modulus operator error out.
Use ** to stick to integers:
for x in range(20, 50):
print(x, math.factorial(x), 2 ** x, math.factorial(x) % (2 ** x))
Integer operations are only limited to how much memory is available, and for x = 23 the correct value is calculated, continuing to work correctly all the way to x = 49:
>>> x = 23
>>> print(x, math.factorial(x), 2 ** x, math.factorial(x) % (2 ** x))
23 25852016738884976640000 8388608 6815744
>>> x = 49
>>> print(x, math.factorial(x), 2 ** x, math.factorial(x) % (2 ** x))
49 608281864034267560872252163321295376887552831379210240000000000 562949953421312 492581209243648
Note that for even for smaller floating point modulus calculations, you really should be using the math.fmod() function, for reasons explained in the documentation. It too fails for this case however, again because you are reaching beyond the limits of floating point math:
>>> print(x, math.factorial(x), math.pow(2, x), math.fmod(math.factorial(x), math.pow(2, x)))
23 25852016738884976640000 8388608.0 0.0
Yes, You are correct for large numbers modulus gives wrong numbers especially with factorial numbers.
for example :
import math
def comb(n,r):
res= math.factorial(n)/(math.factorial(n-r)*math.factorial(r))
return(float(res))
sum1=0
num=888
for r in range(0,num+1):
sum1 +=comb(num,r)
print(sum1 % 1000000)
gives wrong answer 252480 but the correct answer is 789056 .

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.