Title: Precision bug due to different ordering of units in dimensionality. Fix suggestion: Inherit OrderedDict instead of dict in dimensionality.py in order to force the same order of conversions every time · Issue #167 · python-quantities/python-quantities · GitHub
Open Graph Title: Precision bug due to different ordering of units in dimensionality. Fix suggestion: Inherit OrderedDict instead of dict in dimensionality.py in order to force the same order of conversions every time · Issue #167 · python-quantities/python-quantities
X Title: Precision bug due to different ordering of units in dimensionality. Fix suggestion: Inherit OrderedDict instead of dict in dimensionality.py in order to force the same order of conversions every time · Issue #167 · python-quantities/python-quantities
Description: Hi, We need our input values to always be consistent. Currently, the conversion factors in quantities change depending on the order that dimensionality picks for the units. It's using dict which seems to return different sequences for th...
Open Graph Description: Hi, We need our input values to always be consistent. Currently, the conversion factors in quantities change depending on the order that dimensionality picks for the units. It's using dict which se...
X Description: Hi, We need our input values to always be consistent. Currently, the conversion factors in quantities change depending on the order that dimensionality picks for the units. It's using dict whic...
Opengraph URL: https://github.com/python-quantities/python-quantities/issues/167
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Precision bug due to different ordering of units in dimensionality. Fix suggestion: Inherit OrderedDict instead of dict in dimensionality.py in order to force the same order of conversions every time","articleBody":"Hi,\r\n\r\nWe need our input values to always be consistent. Currently, the conversion factors in quantities change depending on the order that dimensionality picks for the units. It's using dict which seems to return different sequences for the units and thus different conversion steps using inherently different conversion factors. It seems that using an OrderedDict always ensures the same sequence of conversions. I'm not a 100% sure about this because I don't know how the order of units pushed to this dimensionality dict is decided, but using an OrderedDict does seem to work much better. \r\n\r\nHere is a `float_test.py` test you can run to check this issue (it's in quantities 0.12.2 and quantities \r\n 0.12.3 both and we're using Python 2.7.15 and Centos 7 :\r\n\r\nfrom quantities import *\r\nfeet = UnitQuantity('feet', ft, symbol='feet')\r\ndfl = 1.0/310.000 * degrees/feet/lbf\r\nvar = Quantity(dfl) * 1.0\r\nprint(\"var.dimensionality_before_conversion:\",var.dimensionality)\r\nvar.units = m ** -2 * rad * s ** 2 * kg ** -1\r\nprint(\"var.dimensionality_after\",var.dimensionality)\r\nprint (\"converted magnitude\", var.magnitude.tolist())\r\n\r\n\r\nWhen you run this several times using bash, it should catch the issue quickly (for some reason it's not so easy catching it when looping it through python, it seems that the order is decided once per python run):\r\n`~/float_bash`\r\n\r\nrm ~/float_output\r\nfor i in {0..10}\r\ndo\r\n echo \"#########################################################\" \u003e\u003e ~/float_output\r\n python float_test.py \u003e\u003e ~/float_output\r\ndone\r\ncat ~/float_output\r\n\r\n\r\nRun it using:\r\n`~/floatbash | grep -E \"dimensionality|converted\"`\r\n\r\nOutput:\r\n('var.dimensionality_before_conversion:', Dimensionality(**{pound_force: -1, feet: -1, arcdegree: 1}**))\r\n('var.dimensionality_after', Dimensionality(**{radian: 1, second: 2, kilogram: -1, meter: -2})**)\r\n('converted magnitude', **4.152544497733612e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality(**{pound_force: -1, arcdegree: 1, feet: -1}**))\r\n('var.dimensionality_after', Dimensionality(**{radian: 1, second: 2, meter: -2, kilogram: -1})**)\r\n('converted magnitude', **4.152544497733611e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({pound_force: -1, feet: -1, arcdegree: 1}))\r\n('var.dimensionality_after', Dimensionality({radian: 1, second: 2, kilogram: -1, meter: -2}))\r\n('converted magnitude', **4.152544497733612e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({pound_force: -1, feet: -1, arcdegree: 1}))\r\n('var.dimensionality_after', Dimensionality({radian: 1, second: 2, kilogram: -1, meter: -2}))\r\n('converted magnitude', **4.152544497733612e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({pound_force: -1, arcdegree: 1, feet: -1}))\r\n('var.dimensionality_after', Dimensionality({radian: 1, second: 2, meter: -2, kilogram: -1}))\r\n('converted magnitude'**, 4.152544497733611e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({pound_force: -1, arcdegree: 1, feet: -1}))\r\n('var.dimensionality_after', Dimensionality({radian: 1, second: 2, meter: -2, kilogram: -1}))\r\n('converted magnitude', 4.152544497733611e-05)\r\n('var.dimensionality_before_conversion:', Dimensionality({pound_force: -1, arcdegree: 1, feet: -1}))\r\n('var.dimensionality_after', Dimensionality({radian: 1, second: 2, meter: -2, kilogram: -1}))\r\n('converted magnitude', 4.152544497733611e-05)\r\n('var.dimensionality_before_conversion:', Dimensionality({pound_force: -1, arcdegree: 1, feet: -1}))\r\n('var.dimensionality_after', Dimensionality({radian: 1, second: 2, meter: -2, kilogram: -1}))\r\n('converted magnitude', 4.152544497733611e-05)\r\n('var.dimensionality_before_conversion:', Dimensionality({pound_force: -1, arcdegree: 1, feet: -1}))\r\n('var.dimensionality_after', Dimensionality({radian: 1, second: 2, meter: -2, kilogram: -1}))\r\n('converted magnitude', 4.152544497733611e-05)\r\n('var.dimensionality_before_conversion:', Dimensionality({pound_force: -1, arcdegree: 1, feet: -1}))\r\n('var.dimensionality_after', Dimensionality({radian: 1, second: 2, meter: -2, kilogram: -1}))\r\n('converted magnitude', 4.152544497733611e-05)\r\n('var.dimensionality_before_conversion:', Dimensionality({pound_force: -1, arcdegree: 1, feet: -1}))\r\n('var.dimensionality_after', Dimensionality({radian: 1, second: 2, meter: -2, kilogram: -1}))\r\n('converted magnitude', 4.152544497733611e-05)\r\n\r\n\r\nAs you can see, the magnitude can result in either:\r\n\r\n**4.152544497733611e-05**\r\nDimensionality({pound_force: -1, arcdegree: 1, feet: -1}))\r\nDimensionality({radian: 1, second: 2, meter: -2, kilogram: -1}))\r\n\r\nor \r\n\r\n**4.152544497733612e-05.** \r\nDimensionality({pound_force: -1, feet: -1, arcdegree: 1})\r\nDimensionality({radian: 1, second: 2, kilogram: -1, meter: -2}))\r\n\r\nThis occurs due to different calculation paths taken due to different orderings of the Dimensionality dictionary due to different conversion factors.\r\n\r\nI traced the calculations to the following that can be done manually in python by extracting the values of when it loops through the dimensionality array to do the conversion:\r\nCALCULATION ONE:\r\n\r\npython\u003e\u003e\u003e 1/.3048\r\n3.280839895013123\r\npython\u003e\u003e\u003e 3.280839895013123 * 0.017453292519943295\r\n0.057261458398764085\r\npython\u003e\u003e\u003e 1/ 0.057261458398764085\r\n17.463753595587495\r\npython\u003e\u003e\u003e 0.057261458398764085 * 4.4482216152605**-1\r\n0.012872887942974195\r\npython\u003e\u003e\u003e 0.012872887942974195 * 1/310\r\n**4.152544497733611e-05**\r\n#\r\nCALCULATION TWO:\r\npython\u003e\u003e\u003e 1/4.4482216152605\r\n0.2248089430997105\r\npython\u003e\u003e\u003e 0.2248089430997105/0.3048\r\n0.7375621492772654\r\npython\u003e\u003e\u003e 0.7375621492772654 * 0.017453292519943295\r\n0.012872887942974197\r\npython\u003e\u003e\u003e 0.012872887942974197 * 1/310.0\r\n**4.152544497733612e-05**\r\n\r\nAs a very very quick fix, when I change dimensionality.py to include this change:\r\n`\r\nfrom collections import OrderedDict\r\nclass Dimensionality(OrderedDict):\r\n`\r\nIt is always consistent because it goes down the same sequence of unit conversions and the same conversion factors leading to consistent behavior which we need. \r\nOutput:\r\n$ ~/floatbash | grep -E \"dimensionality|converted\"\r\n('var.dimensionality_before_conversion:', Dimensionality({arcdegree: 1, feet: -1, pound_force: -1}))\r\n('var.dimensionality_after', Dimensionality({meter: -2, radian: 1, second: 2, kilogram: -1}))\r\n('converted magnitude', **4.152544497733611e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({arcdegree: 1, feet: -1, pound_force: -1}))\r\n('var.dimensionality_after', Dimensionality({meter: -2, radian: 1, second: 2, kilogram: -1}))\r\n('converted magnitude', **4.152544497733611e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({arcdegree: 1, feet: -1, pound_force: -1}))\r\n('var.dimensionality_after', Dimensionality({meter: -2, radian: 1, second: 2, kilogram: -1}))\r\n('converted magnitude', **4.152544497733611e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({arcdegree: 1, feet: -1, pound_force: -1}))\r\n('var.dimensionality_after', Dimensionality({meter: -2, radian: 1, second: 2, kilogram: -1}))\r\n('converted magnitude', **4.152544497733611e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({arcdegree: 1, feet: -1, pound_force: -1}))\r\n('var.dimensionality_after', Dimensionality({meter: -2, radian: 1, second: 2, kilogram: -1}))\r\n('converted magnitude', **4.152544497733611e-05)**\r\n('var.dimensionality_before_conversion:', Dimensionality({arcdegree: 1, feet: -1, pound_force: -1}))\r\n('var.dimensionality_after', Dimensionality({meter: -2, radian: 1, second: 2, kilogram: -1}))\r\n('converted magnitude', **4.152544497733611e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({arcdegree: 1, feet: -1, pound_force: -1}))\r\n('var.dimensionality_after', Dimensionality({meter: -2, radian: 1, second: 2, kilogram: -1}))\r\n('converted magnitude', **4.152544497733611e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({arcdegree: 1, feet: -1, pound_force: -1}))\r\n('var.dimensionality_after', Dimensionality({meter: -2, radian: 1, second: 2, kilogram: -1}))\r\n('converted magnitude', **4.152544497733611e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({arcdegree: 1, feet: -1, pound_force: -1}))\r\n('var.dimensionality_after', Dimensionality({meter: -2, radian: 1, second: 2, kilogram: -1}))\r\n('converted magnitude', **4.152544497733611e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({arcdegree: 1, feet: -1, pound_force: -1}))\r\n('var.dimensionality_after', Dimensionality({meter: -2, radian: 1, second: 2, kilogram: -1}))\r\n('converted magnitude', **4.152544497733611e-05**)\r\n('var.dimensionality_before_conversion:', Dimensionality({arcdegree: 1, feet: -1, pound_force: -1}))\r\n('var.dimensionality_after', Dimensionality({meter: -2, radian: 1, second: 2, kilogram: -1}))\r\n('converted magnitude', **4.152544497733611e-05**)\r\n\r\nHowever, I am unsure whether this change to OrderedDict will work for all the methods you have implemented within dimensionality. Also, I'm not sure why the arcdegree, feet, pound_force is alphabetical but meter, radian, second, kilogram isn't. \r\n\r\nWhat are your thoughts? \r\n\r\nCan we add this change in as it might help others as well in consistency with unit conversions and reduce unexpected results? Our stuff is time critical, so it would be good to know if we can atleast put this change in ourselves if it can't be put in an official release\r\n\r\nThanks!","author":{"url":"https://github.com/vrindger","@type":"Person","name":"vrindger"},"datePublished":"2019-12-05T16:29:38.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":7},"url":"https://github.com/167/python-quantities/issues/167"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:ff0b5e88-93ed-0659-9477-a0c853d80a9f |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | A668:2FF188:5CCCA18:7DC30CB:697373AF |
| html-safe-nonce | 5a527640e0d734d41f5be707d8883c1f9be59a6d594a50c5a89f40e59082a10f |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBNjY4OjJGRjE4ODo1Q0NDQTE4OjdEQzMwQ0I6Njk3MzczQUYiLCJ2aXNpdG9yX2lkIjoiNjk4NDA1NDYzNjg1MTQ1ODk5MSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 736b4379e7f2eb0892c978686cf7ccda261fb6b413b0743fcd5df4cbce726264 |
| hovercard-subject-tag | issue:533459323 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python-quantities/python-quantities/167/issue_layout |
| twitter:image | https://opengraph.githubassets.com/0e5bb8885ce635a42ad91c2021e9a457e0c9736ba1a90319e14c7f496691bd78/python-quantities/python-quantities/issues/167 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/0e5bb8885ce635a42ad91c2021e9a457e0c9736ba1a90319e14c7f496691bd78/python-quantities/python-quantities/issues/167 |
| og:image:alt | Hi, We need our input values to always be consistent. Currently, the conversion factors in quantities change depending on the order that dimensionality picks for the units. It's using dict which se... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | vrindger |
| hostname | github.com |
| expected-hostname | github.com |
| None | 4cf879a11b0a28a85543899a36aaee9ec9ca2fb7bedad86c0da5731193c95f01 |
| turbo-cache-control | no-preview |
| go-import | github.com/python-quantities/python-quantities git https://github.com/python-quantities/python-quantities.git |
| octolytics-dimension-user_id | 222003 |
| octolytics-dimension-user_login | python-quantities |
| octolytics-dimension-repository_id | 560911 |
| octolytics-dimension-repository_nwo | python-quantities/python-quantities |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 560911 |
| octolytics-dimension-repository_network_root_nwo | python-quantities/python-quantities |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | fe8be790582ef7a55477ce1918ac0ed16b106d31 |
| ui-target | canary-2 |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width