Python, different rounding from variable, and hardcoded value - python

I have a simple math formula that results in a decimal number (0.97745) that I want to round to 4 numbers.
When I do that from my evaluated variable I get (0.9774), but when I hardcode that number into function round(), I get 0.9775
Here is the code
zero = 0.9700
effective_beta = 0.00745
loan = {}
loan['beta2'] = 0.0
loan['beta3'] = 0.0
mrktdiff_2 =0.08880400
mrktdiff_3 = 0.026463592000
forecasted_pt = (float(zero) + float(effective_beta) + float(loan['beta2'] or 0.) * float(mrktdiff_2) +
float(loan['beta3'] or 0.) * float(mrktdiff_3))
print("before rounding forecastedpt is ")
print(forecasted_pt)
print("after rounding")
print(round(forecasted_pt,4))
print("Dont get this part")
print(round(0.97745,4))
The reason why I use the float operators is due to the that these variables are dynamic and sometimes can result in string / null values.
Also when I run the same code in php I get the 0.9775 value for this.
Edit:
I ran the code in katacoda.com editor, and got the following:
before rounding forecastedpt is
0.97745
after rounding
0.9774
Dont get this part
0.9775
But running it in repl.com I get the first value as: 0.97744999999999 so I guess it could be in the precision of the expression itself

try it :
zero = 0.9700
effective_beta = 0.00745
loan = {}
loan['beta2'] = 0.0
loan['beta3'] = 0.0
mrktdiff_2 =0.08880400
mrktdiff_3 = 0.026463592000
forecasted_pt = (float(zero) + float(effective_beta) + float(loan['beta2'] or 0.) * float(mrktdiff_2) + float(loan['beta3'] or 0.) * float(mrktdiff_3))
print("before rounding forecastedpt is ")
print(forecasted_pt)
print("after rounding")
print(round(forecasted_pt,5))
numb = round(forecasted_pt,5)
print(round(numb,4))
print("Dont get this part")
print(round(0.97745,4))
the output:
before rounding forecastedpt is
0.9774499999999999
after rounding
0.97745
0.9775
Dont get this part
0.9775
the round function in any language dont round all entire number its strip the numbers to round only the last number of it.

From the python documentation:
Note: The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float. See Floating Point Arithmetic: Issues and Limitations for more information.

Try this:
I remember on my statistics class 10 years ago. My Professor has always been advising us to round the calculation up to 6 decimal points as statistics is all about estimation, it counts alot.
zero = 0.9700
effective_beta = 0.00745
loan = {}
loan['beta2'] = 0.0
loan['beta3'] = 0.0
mrktdiff_2 =0.08880400
mrktdiff_3 = 0.026463592000
forecasted_pt = round((float(zero) + float(effective_beta) + float(loan['beta2'] or 0.) * float(mrktdiff_2) + float(loan['beta3'] or 0.) * float(mrktdiff_3)),6)
print(round(forecasted_pt,4))

Related

Float divisions returning wierd results

Im trying to do a project and for some reason the same divisions give me different results. I am trying to check if 2 divisions are equal and give me the same results but When I try 5.99/1 and 0.599/0.1 the script says that they are different while they are supposed to return the same results. I figured out what the problem is that 5.99/1 = 5.99 and 0.599/0.1 = 5.989999999999999but I cant find a fix for this.
You can find the reason in this answer: https://stackoverflow.com/a/588014/11502612
I have written a possible solution for you:
Code:
a = 5.99 / 1
b = 0.599 / 0.1
a_str = "{:.4f}".format(5.99 / 1)
b_str = "{:.4f}".format(0.599 / 0.1)
print(a, b)
print(a_str, b_str)
print(a == b)
print(a_str == b_str)
Output:
>>> python3 test.py
5.99 5.989999999999999
5.9900 5.9900
False
True
As you can see below I have converted the result of division to a formatted string and I check them instead of default floating type.

KeyError with a poisson process using pandas

I am trying to create a function which will simulate a poison process for a changeable dt and total time, and have the following:
def compound_poisson(lamda,mu,sigma,dt,T):
points = pd.Series(0)
out = pd.Series(0)
inds = simple_poisson(lamda,dt,T)
for ind in inds.index:
if inds[ind+dt] > inds[ind]:
points[ind+dt] = np.random.normal(mu,sigma)
else:
points[ind+dt] = 0
out = out.append(np.cumsum(points),ignore_index=True)
out.index = np.linspace(0,T,int(T/dt + 1))
return out
However, I receive a "KeyError: 0.010000000000000002", which should not be in the index at all. Is this a result of being lax with float objects?
In short, yes, it's a floating point error. It's quite hard to know how you got there, but probably something like this:
>>> 0.1 * 0.1
0.010000000000000002
Maybe use round?

format() function is always returning "0.00"

I have some calculation that I am running that would provide a double/float back:
a = float(4)
b = float(56100)
c = a / b
Now when run the script, I get this:
7.1301e-05
I just need to format this response so that I get 7.13. But when I try to do this I get 0.00:
percentage_connections_used = float(a) / float(b)
percentage_float = float(percentage_connections_used)
print(format(percentage_float, '.2f'))
I can't seem to figure out why it would return 0 when trying to format it. Can someone possibly tell me what is going on? This is Python 2.7
I think your format is correct, but when you try to round to 2 decimal places It actually rounds to 0.00.
7.8125e-05 = 0.000078125
When rendered as 2 decimals, you get 0.00.
You could do a little string manipulation to parse out the 7.8125 figure by using:
d = float(str(c).split('e')[0])
It's a little verbose, though, and maybe someone in the community can do better.
By the way, I get 7.1301...e-05 when I run a/b.
7.8125e-05 is the same as 0.000078125 so formatting it with only two decimal points gives you 0.00. You could do '.7f' which would get you 0.0000713. If you want it to output in scientific notation, you should do that explicitly. Try this:
a = float(4)
b = float(56100)
c = a / b
print("{:.2e}".format(c))

Python: forcing precision on a floating point number in json?

(update)
Here's the actual problem I'm seeing. Note that round() doesn't seem to be doing the trick.
Here's my code:
t0=time.time()
# stuff
t1=time.time()
perfdat={'et1' : round(t1-t0,6), 'et2': '%.6f'%(t1-t0)}
And the dict and json output, respectively:
{'et2': '0.010214', 'et1': 0.010214000000000001}
{"et2":"0.010214","et1":0.010214000000000001}
(end update)
I've got a floating point value that has a lot of extra digits of precision that I don't need. Is there a way to truncate those digits when formatting a json string?
I can get the truncation I need if I format the value as a string, but I would like to transmit the value as a (truncated) number.
import json
v=2.030000002
json.dumps({'x':v}) # would like to just have 2.030
'{"x": 2.030000002}'
s= '%.3f' % (v) # like this, but not as a string
json.dumps({'x' : s})
'{"x": "2.030"}'
Wrap the number into a float:
>>> s = float('%.3f' % (v))
>>> json.dumps({'x' : s})
{"x": 2.03}
Builtin function round can help
In [16]: v=2.030000002
In [17]: json.dumps({'x': round(v, 3)})
Out[17]: '{"x": 2.03}'
This is something I found from from the Python Standard library:
"Unlike hardware based binary floating point, the decimal module has a user alterable precision (defaulting to 28 places) which can be as large as needed for a given problem:
>>> from decimal import *
>>> getcontext().prec = 6
>>> Decimal(1) / Decimal(7)
Decimal('0.142857')
>>> getcontext().prec = 28
>>> Decimal(1) / Decimal(7)
Decimal('0.1428571428571428571428571429')
"
A better import statement would be:
from decimal import getcontext, Decimal
Then you could apply those same functions to specify an arbitrary precision. Hope this helps! I haven't actually used this before.
For your case: (still has the trailing zero issue)
getcontext().prec = 3
s = '2.030'
var = float(Decimal(s))
var returns 2.03
This following approach seems promising:
import json
v = 2.030000002
result = []
for part in json.JSONEncoder().iterencode({'x': v}):
try:
tmp = round(float(part), 3)
except ValueError:
pass
else:
part = '{:.3f}'.format(tmp)
result.append(part)
result = ''.join(result)
print result # -> {"x": 2.030}

Convert Scientific Notation to Float

Encountered a problem whereby my JSON data gets printed as a scientific notation instead of a float.
import urllib2
import json
import sys
url = 'https://bittrex.com/api/v1.1/public/getmarketsummary?market=btc-quid'
json_obj = urllib2.urlopen(url)
QUID_data = json.load(json_obj)
QUID_MarketName_Trex = QUID_data["result"][0]["MarketName"][4:9]
QUID_Last_Trex = QUID_data["result"][0]["Last"]
QUID_High_Trex = QUID_data["result"][0]["High"]
QUID_Low_Trex = QUID_data["result"][0]["Low"]
QUID_Volume_Trex = QUID_data["result"][0]["Volume"]
QUID_BaseVolume_Trex = QUID_data["result"][0]["BaseVolume"]
QUID_TimeStamp_Trex = QUID_data["result"][0]["TimeStamp"]
QUID_Bid_Trex = QUID_data["result"][0]["Bid"]
QUID_Ask_Trex = QUID_data["result"][0]["Ask"]
QUID_OpenBuyOrders_Trex = QUID_data["result"][0]["OpenBuyOrders"]
QUID_OpenSellOrders_Trex = QUID_data["result"][0]["OpenSellOrders"]
QUID_PrevDay_Trex = QUID_data["result"][0]["PrevDay"]
QUID_Created_Trex = QUID_data["result"][0]["Created"]
QUID_Change_Trex = ((QUID_Last_Trex - QUID_PrevDay_Trex)/ QUID_PrevDay_Trex)*100
QUID_Change_Var = str(QUID_Change_Trex)
QUID_Change_Final = QUID_Change_Var[0:5] + '%'
print QUID_Last_Trex
It prints the following value; 1.357e-05.
I need this to be a float with 8 chars behind the decimal (0.00001370)
As you can see here --> http://i.imgur.com/FCVM1UN.jpg, my GUI displays the first row correct (using the exact same code).
You are looking at the default str() formatting of floating point numbers, where scientific notation is used for sufficiently small or large numbers.
You don't need to convert this, the value itself is a proper float. If you need to display this in a different format, format it explicitly:
>>> print(0.00001357)
1.357e-05
>>> print(format(0.00001357, 'f'))
0.000014
>>> print(format(0.00001357, '.8f'))
0.00001357
Here the f format always uses fixed point notation for the value. The default precision is 6 digits; the .8 instructs the f formatter to show 8 digits instead.
In Python 3, the default string format is essentially the same as format(fpvalue, '.16g'); the g format uses either a scientific or fixed point presentation depending on the exponent of the number. Python 2 used '.12g'.
You can use print formatting:
x = 1.357e-05
print('%f' % x)
Edit:
print('%.08f' % x)
There are some approaches:
#1 float(...) + optionally round() or .format()
x = float(1.357e-05)
round(x, 6)
"{:.8f}".format(x)
#2 with decimal class
import decimal
tmp = decimal.Decimal('1.357e-05')
print('[0]', tmp)
# [0] 0.00001357
tmp = decimal.Decimal(1.357e-05)
print('[1]', tmp)
# [1] 0.0000135700000000000005188384444299032338676624931395053863525390625
decimal.getcontext().prec = 6
tmp = decimal.getcontext().create_decimal(1.357e-05)
print('[2]', tmp)
# [2] 0.0000135700
#3 with .rstrip(...)
x = ("%.17f" % n).rstrip('0').rstrip('.')
Note: there are counterparts to %f:
%f shows standard notation
%e shows scientific notation
%g shows default (scientific if 5 or more zeroes)

Categories