Convert Scientific Notation to Int Precision Problem
Closed this issue · 2 comments
I was using the client.trade()
function to buy Cobinhood, here is the sell order:
"sells": {
"amount": "-2.367e+21",
"amountFilled": null,
"amountGet": "447363000000000000",
"amountGive": "2.367e+21",
"availableVolume": "2.362e+21",
"availableVolumeBase": "446418000000000000",
"ethAvailableVolume": "2362",
"ethAvailableVolumeBase": "0.446418",
"expires": "5292321",
"id": "11fe2d956845bb5fc2ca05b6d655f04c43b5caaaac798a95f157d3d1964a853e_sell",
"nonce": "3592513099",
"price": "0.000189",
"r": "0x16a39aa3d4c1494799f5130530425b989a52b82d48e007f8daa1a49e991e528c",
"s": "0x3084e4f66ac78795ce688451fda68840e5373e9e2fbcbc613f3208f9e03b766a",
"tokenGet": "0x0000000000000000000000000000000000000000",
"tokenGive": "0xb2f7eb1f2c37645be61d73953035360e768d81e6",
"updated": "2018-03-19T11:02:08.951Z",
"user": "0xa330a750abca19b79640ee7db1b9d06226b6486d",
"v": 28
}
As you can see the amount give is 2.367e+21 which should be 2367 cobinhood (18 decimal). However when you convert this scientific notation to int. Here is result:
>>> int(float("2.367e+21"))
2367000000000000262144
This will end up with hex value: 00000000000000000000000000000000000000000000008050b94718b5a00000
The correct amount give should be 2367000000000000000000 with hex value: 00000000000000000000000000000000000000000000008050b94718b59c0000
This leads to a transaction failure.
I do the following precision test:
>>> int(float("2.367e+6"))
2367000
>>> int(float("2.367e+10"))
23670000000
>>> int(float("2.367e+20"))
236700000000000000000
>>> int(float("2.367e+21"))
2367000000000000262144
>>> int(float("2.367e+26"))
236700000000000012188647424
As you can see that starting from 10 to 21 power, the results are wrong.
I found the solution. We should use decimal library Decimal type instead of float:
Decimal numbers can be represented exactly. In contrast, numbers like 1.1 and 2.2 do not have exact representations in binary floating point. End users typically would not expect 1.1 + 2.2 to display as 3.3000000000000003 as it does with binary floating point.