How to avoid rounding float numbers in python? - python

I have some json objects and when I convert them into dictionary in python they will rounded:
-112.07393329999999 -> -112.0739333
My code is:
for line in open("c:\\myfile","r+").readlines():
d = json.loads(line)
logtv = d['logtv']

It's just a more compact representation of the same (binary, 64-bit) number.
In [12]: -112.07393329999999 == -112.0739333
Out[12]: True
In [17]: struct.pack('d', -112.0739333)
Out[17]: 've\xbcR\xbb\x04\\\xc0'
In [18]: struct.pack('d', -112.07393329999999)
Out[18]: 've\xbcR\xbb\x04\\\xc0'
If you want this exact decimal, there's no way to represent it as a number in JSON. You'll have to use strings in your JSON, Decimals/strings in your python and decimal fields in your DB.
SQL Server Floats are at most 64-bit (53-bit significand) as well.

The answer is don't use floats. In most languages floats only have about 6 digits of significance and not too many more for doubles (note python floats are doubles). Use decimals if you know the exact precision. For JSON send it as a string or an int with an implied decimal point.
soap box: floats are very much overused. Floats should not be used by anything that you wouldn't represent with scientific notation, as that is what they really are underneath.
Note: Databases do not usually use floating point numbers, they use fixed point numbers. Which is exactly what a decimal is.
clarification
before you write the json file do something like
with open("c:\\myfile","w") as my_file:
for key in d:
if isinstance(d[key], Decimal):
d[key] = str(d[key])
my_file.write(json.dumps(d))
then when reading the json, you can just put the value into the database as is or convert it back to Decimal if you need to work with it more.

Related

float number with leading zero at end on python

I want to convert string number to float and keep zeros at the end like this f=float('.270') and f should be 0.270, not 0.27 or '0.270' how I can do it?
Depending of the application, you should use the Decimal lib - specially if you are dealing with critical calculations like money
https://docs.python.org/3.8/library/decimal.html
import decimal
decimal.getcontext().prec = 3
f = decimal.Decimal('0.270')
print(f)
Or simply "%.3f" % f
Have you considered saving the float as a string rather than a float? If needed for calculations then it can be casted to a float. If you need to have this for significant figures, then this article on rounding numbers in Python should help. It uses the format() method.
I hope this was able to help!
phylo

Convert a scientific notation to decimal number, and still keeping the data format as float64

I have a simple question.
I am using the numpy.std formula to calculate the standard deviation. However, the result comes as a number in scientific notation.
Therefore I am asking, How to convert a scientific notation to decimal number, and still keep the data format as float64 ?
Or is there any workaround to get the initial result as a decimal number?
Solutions such as this:
stdev = format(stdev, '.10f')
converts the data into a string object, which I don't want.
ere is my code:
stdev = numpy.std(dataset)
print(stdev)
Result: 4.999999999999449e-05
print(stdev.dtype)
Result: float64
Expected result
I willing to have a result as a decimal number in a float64 format.
I suppose it is just a matter of representation since the data type, as you showed, is still float64.
If this is right, you can just print as a formatted string:
>>> x = 123456789e-15
>>> print(x)
1.23456789e-07
>>> print("{:.15f}".format(x))
0.000000123456789
The .15f specifies that you want a float format with 15 decimals.
From python 3.6 you can use the f-string format:
print(f"{x:.15f}")
0.000000123456789
Have a look at the string format documentation
You confuse representation and internal storage. By default, Python will show the value in the scientific form. You can force another form of representation - but you cannot affect the value itself.
Vanilla Python does not have a notion of float64 (it is not that great for exact calculations) - but numpy does

How to convert hex to IEEE floating point python

I want to convert this hex string '8436d4ccd436d3333' to IEEE floating point. I've try to do this with struct.unpack but it's requires a string argument of length 4.
struct.unpack('>f', binascii.unhexlify('8436d999a436e0000'))
I'm using this website to verify if my conversion attempts are correct : https://gregstoll.dyndns.org/~gregstoll/floattohex/ but I can't find a way to do this.
Thanks for any help
At a guess, each hex string contains two single-precision floating-point values, not one, and the initial 8 is part of the whatever message protocol is being used, and not a part of either of those floats. With that guess, I get some plausible-looking numbers:
>>> struct.unpack('>ff', binascii.unhexlify('436d4ccd436d3333'))
(237.3000030517578, 237.1999969482422)
>>> struct.unpack('>ff', binascii.unhexlify('436d999a436e0000'))
(237.60000610351562, 238.0)
And to reinforce the plausibility, here's what I get by encoding the corresponding 1-digit-past-the-decimal-point values:
>>> binascii.hexlify(struct.pack('>ff', 237.3, 237.2))
b'436d4ccd436d3333'
>>> binascii.hexlify(struct.pack('>ff', 237.6, 238.0))
b'436d999a436e0000'

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.

How to store exponential values using python

I am looking for a way to perform a digit divided by larger value(2/5000000) and then store that value in table, but the problem is when i save that value, only 0 is stored , instead of correct value.I tried with float, double precision, but still only 0 is stored, is there any other way .
Thank you
Remember to operate on floating numbers, and not convert it after the operation. E.g. 2/5000000.
Also, use the Decimal library, if you are looking for more accurate decimals.
You need to use floating point division. To be explicit, you can cast ints to float:
>>> a = 2
>>> b = 5000000
>>> c = a/float(b)
>>> c
4e-07
You can cast either a or b to float.

Categories