Clean way to convert string to floating point number with specific precision? - python

I'm trying to convert strings of numbers that come from the output of another program into floating point numbers with two forced decimal places (including trailing zeros).
Right now I'm converting the strings to floats, then separately specifying precision (two decimal places), then converting back to float to do numeral comparisons on later.
# convert to float
float1 = float(output_string[6])
# this doesn't guarantee two decimal places in my output
# eg: -36.55, -36.55, -40.34, -36.55, -35.7 (no trailing zero on the last number)
nice_float = float('{0:.2f}'.format(float1))
# this works but then I later need to convert back into a float
# string->float->string->float is not super clean
nice_string = '{0:.2f}'.format(float1)
Edit for clarity:
I have a problem with the display in that I need that to show exactly two decimal places.
Is there a way to convert a string to a floating point number rounded to two decimal places that's cleaner than my implementation which involves converting a string to a float, then the float back into a formatted string?

Related

Large decimal numbers with function math.modf

I am using the function math.modf which separates the integer and decimal part of a number as follows:
decimal_part, integer_part = math.modf(x)
Where x is a decimal number.
An example for a small number is as follows:
x = 1993.0787353515625
decimal_part = 0.0787353515625, integer_part = 1993.0
But when I work with very large numbers the following happens:
x = 6.797731511223558e+44
decimal_part = 0.0, integer_part = 6.797731511223558e+44
In this case it doesn't save the result in the decimal part and appears 0.0. And the same happens for numbers up to 300 digits. But when the number x has at least 360 digits, the following error appears:
OverflowError: int too large to convert to float.
I would like to save the decimal part of large numbers of at least 300 digits without overflowing the register where the decimal part is stored. And I would like to avoid the error in numbers with more than 360 digits: "OverflowError: int too large to convert to float".
How can I solve it?
Due to the extra information it has to save, float needs more space than int. But let's break this down:
The number 6.797731511223558e+44 is an integer, which means it has no decimal part, so it will always return 0.0 as decimal.
If you are providing an integer with 300+ digits, it will still be an integer, so the decimal part will still be 0.0, so there's no need to use the function. You are getting that error because you are passing a very large int that is converted to float to give you the result, but this is not necessary since you already know the result.
On the other hand, if you use the function with a float, the function doesn't have problems casting float to float, so it won't show the error.
The number 6.797731511223558e+44 should be a number with a decimal part because it is the result of dividing a number by another number. But python doesn't save the decimal result and 0.0 appears. When we introduce small numbers in the function, it saves the decimal part.

Dealing with decimals with many digits in Pandas,

pd.set_option('display.max_colwidth', None )
pd.set_option('display.float_format', lambda x: '%.200f' % x)
exData = pd.read_csv('AP11.csv',delimiter=';',float_precision=None)
x = exData.loc[:,['A','B']]
y = exData.loc[:,['C']]
x
my original float on excel is 0.1211101931541032183754113717355410323332315436353654273243543132542237415430173719
what is being displayed is
0.12111019315410319341363987177828676067292690277099609375000000000000000000000000000000000000000000000000000000000...
this is not a display issue. something in pandas rounds my float. i don't want to round any number for it will affect the result of my string. because this is originally a string that is converted to a float. i tried to use int64 but it can't handle big numbers. so instead i decided to use floats with "0.mystring" to not get "inf" displayed in pandas. and i get it rounded. is machine learning limited by these missy variables? or is there another way to deal with big numbers without rounding, displaying inf?
Use decimal instead of float. Just put
from decimal import Decimal
at the top of your code, and write your floats as
x = Decimal(0.121110193154103218375411371735541032333231543635365427324354313254223741543017371)
decimal is a library for floats with a dynamic length, rather than rounded.
Generally you should avoid floats, as they can have strange irregularities and roundings. Often when operations are performed on them, they can have a series of zeros and then some other numbers, when it should just have a few decimal places.

struct.unpack with precision after decimal points

I am reading data from a binary file, it contains floating point data of which I want only first 6 digits after decimal point but its printing a pretty long string.
self.dataArray.append(struct.unpack("f", buf)[0])
I tried with this
self.dataArray.append(struct.unpack(".6f", buf)[0])
But it didn't worked.
Thanks in advance
a float isnt a string and a string isnt a float.
all a float is, is a number of bytes interpreted as both a whole number part and a fractional part
the_float = struct.unpack("f", buf)[0]
print "The Float String %0.6f"%(the_float)

append integer with comma in python

I have a function that assigns a number to a variable, and then append this number as an integer in a list. The numbers assigned may or may not have a comma.
for number in values:
list_of_values.append(int(number))
#do a few calculations for some of the numbers in the list
But this will just create a list where each number is rounded to a integer. How can I append the number as an integer and still retain its "true" value, without it being rounded?
edit:
sample values:
"0", "2", "1.5", "0.5", ...
If you wanted to represent real numbers (numbers with decimals behind a decimal point, or, in some locales, after the comma), then you should not use int() to represent these.
Use float() or decimal.Decimal() to represent the numbers instead:
list_of_values.append(float(number))
int() represents the number as an integer number, which by definition do not have a decimal component. If you don't want rounded numbers, don't use integers.
Whether you pick float() or decimal.Decimal() depends on your precision and performance needs. float() arithmetic can be handled in CPU hardware but are less precise (decimals are approximated using binary fractions), decimal.Decimal() preserves precision but arithmetic is slower.
the integer datatype is not able to hold floating values!
therefore you could use the float datatype instead!
list_of_values.append(float(number))

Problems with decimals and scientific notation in Python 2.6.6

I'm having difficulty with decimal values that I need to use for arithmetic in some cases and as strings in others. Specifically I have a list of rates, ex:
rates=[0.1,0.000001,0.0000001]
And I am using these to specify the compression rates for images. I need to initially have these values as numbers because I need to be able to sort them to make sure they are in a specific order. I also want to be able to convert each of these values to strings so I can 1) embed the rate into the filename and 2) log the rates and other details in a CSV file. The first problem is that any float with more than 6 decimal places is in scientific format when converted to a string:
>>> str(0.0000001)
'1e-07'
So I tried using Python's Decimal module but it is also converting some floats to scientific notation (seemingly contrary to the docs I've read). Ex:
>>> Decimal('1.0000001')
Decimal('1.0000001')
# So far so good, it doesn't convert to scientific notation with 7 decimal places
>>> Decimal('0.0000001')
Decimal('1E-7')
# Scientific notation, back where I started.
I've also looking into string formatting as suggested in multiple posts, but I've not had any luck. Any suggestions and pointers are appreciated by this Python neophyte.
You have to specify the string format then:
["%.8f" % (x) for x in rates]
This yields ['0.10000000', '0.00000100', '0.00000010']. Works with Decimal, too.
'{0:f}'.format(Decimal('0.0000001'))
The above should work for you
See % formatting, especially the floating point conversions:
'e' Floating point exponential format (lowercase). (3)
'E' Floating point exponential format (uppercase). (3)
'f' Floating point decimal format. (3)
'F' Floating point decimal format. (3)
'g' Floating point format. Uses lowercase exponential format if exponent is less than -4 or not less than precision, decimal format otherwise. (4)
'G' Floating point format. Uses uppercase exponential format if exponent is less than -4 or not less than precision, decimal format otherwise. (4)
An example, using f format.
>>> ["%10.7f" %i for i in rates]
[' 0.1000000', ' 0.0000010', ' 0.0000001']
>>>
You can also use the newer (starting 2.6) str.format() method:
>>> ['{0:10.7f}'.format(i) for i in rates]
[' 0.1000000', ' 0.0000010', ' 0.0000001']
>>>
Using f-strings:
>>> rates = [0.1, 0.000001, 0.0000008]
>>> [f'{r:.7f}' for r in rates]
['0.1000000', '0.0000010', '0.0000008']
The string format {r:.7f} indicates the number of digits used after the decimal point, which in this case is 7.

Categories