Mark Harrison
Mark Harrison

Reputation: 304662

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"}'

Upvotes: 12

Views: 13189

Answers (4)

martineau
martineau

Reputation: 123541

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}

Upvotes: 2

wgwz
wgwz

Reputation: 2769

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

Upvotes: 2

l'L'l
l'L'l

Reputation: 47282

Wrap the number into a float:

>>> s = float('%.3f' % (v))
>>> json.dumps({'x' : s})
{"x": 2.03}

Upvotes: 7

Konstantin
Konstantin

Reputation: 25369

Builtin function round can help

In [16]: v=2.030000002

In [17]: json.dumps({'x': round(v, 3)})
Out[17]: '{"x": 2.03}'

Upvotes: 2

Related Questions