{"action":"created","issue":{"url":"https://api.github.com/repos/BitShares/bitshares/issues/1308","labels_url":"https://api.github.com/repos/BitShares/bitshares/issues/1308/labels{/name}","comments_url":"https://api.github.com/repos/BitShares/bitshares/issues/1308/comments","events_url":"https://api.github.com/repos/BitShares/bitshares/issues/1308/events","html_url":"https://github.com/BitShares/bitshares/issues/1308","id":55544135,"number":1308,"title":"API should never return doubles","user":{"login":"theoreticalbts","id":10215982,"avatar_url":"https://avatars.githubusercontent.com/u/10215982?v=3","gravatar_id":"","url":"https://api.github.com/users/theoreticalbts","html_url":"https://github.com/theoreticalbts","followers_url":"https://api.github.com/users/theoreticalbts/followers","following_url":"https://api.github.com/users/theoreticalbts/following{/other_user}","gists_url":"https://api.github.com/users/theoreticalbts/gists{/gist_id}","starred_url":"https://api.github.com/users/theoreticalbts/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/theoreticalbts/subscriptions","organizations_url":"https://api.github.com/users/theoreticalbts/orgs","repos_url":"https://api.github.com/users/theoreticalbts/repos","events_url":"https://api.github.com/users/theoreticalbts/events{/privacy}","received_events_url":"https://api.github.com/users/theoreticalbts/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/BitShares/bitshares/labels/theoreticalbts","name":"theoreticalbts","color":"bfe5bf"}],"state":"open","locked":false,"assignee":{"login":"theoreticalbts","id":10215982,"avatar_url":"https://avatars.githubusercontent.com/u/10215982?v=3","gravatar_id":"","url":"https://api.github.com/users/theoreticalbts","html_url":"https://github.com/theoreticalbts","followers_url":"https://api.github.com/users/theoreticalbts/followers","following_url":"https://api.github.com/users/theoreticalbts/following{/other_user}","gists_url":"https://api.github.com/users/theoreticalbts/gists{/gist_id}","starred_url":"https://api.github.com/users/theoreticalbts/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/theoreticalbts/subscriptions","organizations_url":"https://api.github.com/users/theoreticalbts/orgs","repos_url":"https://api.github.com/users/theoreticalbts/repos","events_url":"https://api.github.com/users/theoreticalbts/events{/privacy}","received_events_url":"https://api.github.com/users/theoreticalbts/received_events","type":"User","site_admin":false},"milestone":null,"comments":2,"created_at":"2015-01-26T22:02:13Z","updated_at":"2015-01-27T23:08:30Z","closed_at":null,"body":"\r\nOne common programmer's rule of thumb is \"never use floating point for anything to do with money and accounting, ever, under any circumstances.\"\r\n\r\nUnfortunately, early versions of the code did not strictly stick to this rule of thumb, and for many months now the developers have been waging an ongoing campaign to weed out doubles whenever and wherever they are found.\r\n\r\nTo this end, I want to eliminate doubles from the API entirely.  The main purpose is to help third-party client libraries follow the \"never use floating point for money\" rule, even if the JSON parser turns numbers into doubles and does not provide straightforward hooks to allow the user to override this behavior.  If everything in our API which is a potentially fractional value -- in particular prices -- is a string, then third-party clients will have no problem applying their own parsing function.\r\n\r\nSecondary bonuses include ease of readability and portability.  This ticket was inspired by this regression test failure when testing `blockchain_get_feeds_from_delegate` :\r\n\r\n    failed on line 283\r\n    expect: 283:     \"price\": 2.0000000000000002e-005,\r\n    actual: 283:     \"price\": 2.0000000000000002e-05,\r\n\r\n- The price was entered as `0.00002`, but appears as `2.0000000000000002e-05`.\r\n- Both the loss of \"exactness\" (that final 2) and the scientific notation are undesirable user experience and may even lead to non-idempotency (if a delegate sets their feed to the value returned by `blockchain_get_feeds_from_delegate` for their own account, it should in theory be a no-op, but it may not be due to the combination of output formatting and input parsing)\r\n- Apparently this difference is due to running on two different combinations of OS, compiler, runtime and libraries resulting in `e-05` vs. `e-005`\r\n\r\nI will leave this ticket open until I have had a chance to review all API methods, clean up as many doubles as possible, and note the ones that can't be converted for whatever reason.\r\n"},"comment":{"url":"https://api.github.com/repos/BitShares/bitshares/issues/comments/71748200","html_url":"https://github.com/BitShares/bitshares/issues/1308#issuecomment-71748200","issue_url":"https://api.github.com/repos/BitShares/bitshares/issues/1308","id":71748200,"user":{"login":"theoreticalbts","id":10215982,"avatar_url":"https://avatars.githubusercontent.com/u/10215982?v=3","gravatar_id":"","url":"https://api.github.com/users/theoreticalbts","html_url":"https://github.com/theoreticalbts","followers_url":"https://api.github.com/users/theoreticalbts/followers","following_url":"https://api.github.com/users/theoreticalbts/following{/other_user}","gists_url":"https://api.github.com/users/theoreticalbts/gists{/gist_id}","starred_url":"https://api.github.com/users/theoreticalbts/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/theoreticalbts/subscriptions","organizations_url":"https://api.github.com/users/theoreticalbts/orgs","repos_url":"https://api.github.com/users/theoreticalbts/repos","events_url":"https://api.github.com/users/theoreticalbts/events{/privacy}","received_events_url":"https://api.github.com/users/theoreticalbts/received_events","type":"User","site_admin":false},"created_at":"2015-01-27T23:08:30Z","updated_at":"2015-01-27T23:08:30Z","body":"\r\n> JSON does not allow scientific notation\r\n\r\nhttp://json.org/ begs to differ.  And it's kind of common sense -- in order to be useful, any data interchange format which supports floating point values must have a concise way to represent e.g. `1e300` (which is a legal double value).\r\n"}}