Can Python disable or not used the rounding off a float?
This is my sample
value = 6.30 * 75.73
value:
477.099
I want only to get the value 477.09 without rounding it off.
You can convert to a string and using string split, append just the last 2 digits of the number
num = 477.097
strnum = str(int(num)) + str(num).split(".")[1][:2]
What you want is called truncating, which is notoriously difficult with float values because of the way they are stored.
If you are doing this for the value itself, you can do this;
value = 6.30 * 75.73
value = (( value * 100 ) // 1) * .01
print(value)
This will print
477.09000000000003
which is equivalent to 477.09 for math calculations.
If you are doing this to display the value, then you can convert to a string and just cut off the last digit that you have. Or, if you don't know how many digits there are after the decimal point, you can get the index of the ".", and cut everything that is 2 after that point, as so:
value = 6.30 * 75.73
val_str = str(value)
rounded_str = val_str[:val_str.index('.') + 3]
This will print
477.09
convert value to string(if value an integer then the code will still work, because before the conversion to a string we convert to a float):
value = = 6.30 * 75.73
value_str = str(float(value))
'{:.2f}'.format(float(value_str[:value_str.index('.') + 3]))
Possibly this? (takes about 100 nanoseconds independent of number of digits)
** note, this does not work for negative numbers as written, so it's of limited use.
value = 6.30 * 75.73
print value
print value - value % 0.01
477.097
477.09
does it really truncate?
value = 1./3.
print value - 0.33333333 # see the leftovers
3.333333331578814e-09
print value - value % 0.01
0.33
print (value - value % 0.01) - 0.33 # no leftovers
0.0
(value - value % 0.01) == 0.33
True
You can try this hack with round:
>>> 6.30 * 75.73
>>> 477.099
>>> DIGITS = 2
>>> round(6.30 * 75.73 - 5.0 * 10**(-DIGITS-1), DIGITS)
>>> 477.09
Related
I'm trying to store some values in a while with a variable counter t in a certain way that for example, t reaches 2, certain value gets stored, t reaches 3, value gets stored and so on until 20:
In this example t starts at 1, and dt=0.1. I want that when we reach t=2 do the action:
while t<t_final:
t += dt
tint = int(t)
for i in range(20):
if tint == int(i):
action
break
But I'm not sure if the break does what I want. Which is the best approach?
If i undesrstand correctly dt is a float (0.1 for example). If you want to add 0.1 every time but you want the action happen only when the number is a integer(AKA has no decimals) you will have a floating point problem. for example 0+0.1+0.1+0.1... will never give you 15, it will give you, 14.999999999999963.
You could say if the numbers after the decimal point have a value less than (and some confindence interval) assume is integer:
t= 0
t_final = 20
dt = 0.1
while t<t_final:
t += dt
tDecimals = t%1
if tDecimals < dt: # less than dt or less than 0.1
print(int(t))
#action
Or, i think this is a better option, use a flag and: if the value of t are greater than the value of last t by at least 1 do the action
t= 0
lastInteger = t-1
t_final = 20
dt = 0.1
while t<t_final:
t += dt
if lastInteger + 1 < t:
lastInteger = int(t)
print(int(t))
#action
And another option is use Decimals (are better than floats for a lot of operations)
import decimal
decimal.getcontext().prec = 9 # number of 0 after decimal points
# that decimal will use and save
t= decimal.Decimal('0')
t_final = 20
dt = decimal.Decimal('0.1')
while t<t_final:
t += dt
for i in range(20):
if t == i:
Action
break
I'd like to automatically round numbers to x significant figures, but only their fractional part.
Desired output:
123 >>> 123.00
123.123 >>> 123.12
1.12 >>> 1.12
0.1 >>> 0.10
0.1234 >>> 0.12
0.01234 >>> 0.012
0.0001254 >>> 0.00013
I'm trying to achieve the most simple solution.
I've figured out such a solution:
def round_to_frac_sigfig(num, sigfigs):
sigfig_pos = int(floor(log10(abs(num))))
if sigfig_pos >= 0:
formatter = "{:.%df}" % sigfigs
return formatter.format(num)
else:
ndigits = -sigfig_pos + sigfigs - 1
formatter = "{:.%df}" % ndigits
return formatter.format(num)
If you don't care about the trailing zeros, here's a shorter solution:
def round_to_frac_sigfig(num, sigfigs):
sigfig_pos = int(floor(log10(abs(num))))
if sigfig_pos >= 0:
return round(num, sigfigs)
else:
return round(num, -sigfig_pos + sigfigs - 1)
Python 2 how to do this.Print the value of the series x = 1 + 1/2 + 1/3 + 1/4 + … + 1/n for the user’s input of n.
Here you go:
n = int( input() ) # reading user input
x = 0
for i in range(1, n + 1): # adding 1/1 + 1/2 + 1/3 + ... + 1/n
x += 1.0/i
print(x) # => outputs : 2.283333333333333
There may be a Harmonic Series function in Python packages like math or numpy, or some similar way to deal with it, especially if you need high precision at large values of n. Otherwise, you could just do this:
>>> n = 5
>>> print(sum(1.0/i for i in range(1,n+1)))
2.28333333333
Note that the "1.0" is important for Python 2.x so that it knows to deal with floats. Otherwise things get rounded along the way:
>>> print(sum(1/i for i in range(1,n+1)))
1
I am trying to write a program to calclulate digits of pi using the Nilakantha Series in python. Every time it runs though it will not give me more than 50 decimals. Still learning python so any help is appreciated.
# Program using Nilakantha Series to crunch digits of pi
from math import *
from decimal import *
getcontext().prec = 200 # this is not doing anything
# epsilon is how accurate I want to be to pi
EPSILON = 0.000000000000000000000000000000000000000000000000000001
sum = float(3)
step = 0
i = 2
while abs(pi - sum) >= EPSILON:
step += 1
print (step)
if step % 2 == 1:
sum += 4.0 / (i * (i + 1) * (i + 2))
i += 2
else:
sum -= 4.0 / (i * (i + 1) * (i + 2))
i += 2
print (Decimal(sum))
print (Decimal(pi))
print ("Total itterations: ", step)
print ("Accurate to: ", EPSILON)
You are not using the Decimal class to calculate Pi, but rather the float class. getcontext() affects Decimal, not float.
If you want to use Decimal, modify your code to convert to Decimal before looping. Note that AFAIK, the value of Pi is not available as a decimal in Python, so you need to get the value from someplace else (http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html).
I would like to use the Decimal() data type in python and convert it to an integer and exponent so I can send that data to a microcontroller/plc with full precision and decimal control. https://docs.python.org/2/library/decimal.html
I have got it to work, but it is hackish; does anyone know a better way? If not what path would I take to write a lower level "as_int()" function myself?
Example code:
from decimal import *
d=Decimal('3.14159')
t=d.as_tuple()
if t[0] == 0:
sign=1
else:
sign=-1
digits= t[1]
theExponent=t[2]
theInteger=sign * int(''.join(map(str,digits)))
theExponent
theInteger
For those that havent programmed PLCs, my alternative to this is to use an int and declare the decimal point in both systems or use a floating point (that only some PLCs support) and is lossy. So you can see why being able to do this would be awesome!
Thanks in advance!
You could do this :
[ This is 3 times faster than the other methods ]
d=Decimal('3.14159')
list_d = str(d).split('.')
# Converting the decimal to string and splitting it at the decimal point
# If decimal point exists => Negative exponent
# i.e 3.14159 => "3", "14159"
# exponent = -len("14159") = -5
# integer = int("3"+"14159") = 314159
if len(list_d) == 2:
# Exponent is the negative of length of no of digits after decimal point
exponent = -len(list_d[1])
integer = int(list_d[0] + list_d[1])
# If the decimal point does not exist => Positive / Zero exponent
# 3400
# exponent = len("3400") - len("34") = 2
# integer = int("34") = 34
else:
str_dec = list_d[0].rstrip('0')
exponent = len(list_d[0]) - len(str_dec)
integer = int(str_dec)
print integer, exponent
Performance testing
def to_int_exp(decimal_instance):
list_d = str(decimal_instance).split('.')
if len(list_d) == 2:
# Negative exponent
exponent = -len(list_d[1])
integer = int(list_d[0] + list_d[1])
else:
str_dec = list_d[0].rstrip('0')
# Positive exponent
exponent = len(list_d[0]) - len(str_dec)
integer = int(str_dec)
return integer, exponent
def to_int_exp1(decimal_instance):
t=decimal_instance.as_tuple()
if t[0] == 0:
sign=1
else:
sign=-1
digits= t[1]
exponent = t[2]
integer = sign * int(''.join(map(str,digits)))
return integer, exponent
Calculating the time taken for 100,000 loops for both methods :
ttaken = time.time()
for i in range(100000):
d = Decimal(random.uniform(-3, +3))
to_int_exp(d)
ttaken = time.time() - ttaken
print ttaken
Time taken for string parsing method : 1.56606507301
ttaken = time.time()
for i in range(100000):
d = Decimal(random.uniform(-3, +3))
to_int_exp1(d)
ttaken = time.time() - ttaken
print ttaken
Time taken for convertion to tuple then extract method : 4.67159295082
from functools import reduce # Only in Python 3, omit this in Python 2.x
from decimal import *
d = Decimal('3.14159')
t = d.as_tuple()
theInteger = reduce(lambda rst, x: rst * 10 + x, t.digits)
theExponent = t.exponent
Get the exponent directly from the tuple as you were:
exponent = d.as_tuple()[2]
Then multiply by the proper power of 10:
i = int(d * Decimal('10')**-exponent)
Putting it all together:
from decimal import Decimal
_ten = Decimal('10')
def int_exponent(d):
exponent = d.as_tuple()[2]
int_part = int(d * (_ten ** -exponent))
return int_part, exponent
from decimal import *
d=Decimal('3.14159')
t=d.as_tuple()
digits=t.digits
theInteger=0
for x in range(len(digits)):
theInteger=theInteger+digits[x]*10**(len(digits)-x)