I have a variable in Python containing a floating point number (e.g. num = 24654.123
), and I\'d like to determine the number\'s precision and scale values (in t
If you need to check the number of corresponding digits (of a and b)
def prec_check(a, b):
a = str(a)
b = str(b)
do = bool(True)
n = 0
while do == True:
if a and b and a[n] == a[b]:
n += 1
else:
do = false
return n
Note that this doesn't work with the "Decimal" module.
Basically, you can't with floating point numbers. Using the decimal type would help and if you want really large precision, consider using gmpy, the GNU Multiple Precision library's port to Python.
I found another solution that seems to be simpler, but I'm not sure exactly if it will work for all cases.
import math
x = 1.2345678
def flip(string):
result = ""
for ch in string:
result = ch + result
return result
prec = int(math.log10(float(flip(str(x)))) + 1 # precision as int
Getting the number of digits to the left of the decimal point is easy:
int(log10(x))+1
The number of digits to the right of the decimal point is trickier, because of the inherent inaccuracy of floating point values. I'll need a few more minutes to figure that one out.
Edit: Based on that principle, here's the complete code.
import math
def precision_and_scale(x):
max_digits = 14
int_part = int(abs(x))
magnitude = 1 if int_part == 0 else int(math.log10(int_part)) + 1
if magnitude >= max_digits:
return (magnitude, 0)
frac_part = abs(x) - int_part
multiplier = 10 ** (max_digits - magnitude)
frac_digits = multiplier + int(multiplier * frac_part + 0.5)
while frac_digits % 10 == 0:
frac_digits /= 10
scale = int(math.log10(frac_digits))
return (magnitude + scale, scale)
I think you should consider using the decimal type instead of a float
. The float
type will give rounding errors because the numbers are represented internally in binary but many decimal numbers don't have an exact binary representation.
Not possible with floating point variables. For example, typing
>>> 10.2345
gives:
10.234500000000001
So, to get 6,4 out of this, you will have to find a way to distinguish between a user entering 10.2345
and 10.234500000000001
, which is impossible using floats. This has to do with the way floating point numbers are stored. Use decimal
.
import decimal
a = decimal.Decimal('10.234539048538495')
>>> str(a)
'10.234539048538495'
>>> (len(str(a))-1, len(str(a).split('.')[1]))
(17,15)