Title: naturalsize np.int32 multiplication overflow · Issue #217 · python-humanize/humanize · GitHub
Open Graph Title: naturalsize np.int32 multiplication overflow · Issue #217 · python-humanize/humanize
X Title: naturalsize np.int32 multiplication overflow · Issue #217 · python-humanize/humanize
Description: What did you do? I was using the torchio library, which relies on humanize to return the memory size of image arrays. The images I processed had dimensions 512x512x166, with each pixel being a 32-bit (4-byte) integer. What did you expect...
Open Graph Description: What did you do? I was using the torchio library, which relies on humanize to return the memory size of image arrays. The images I processed had dimensions 512x512x166, with each pixel being a 32-b...
X Description: What did you do? I was using the torchio library, which relies on humanize to return the memory size of image arrays. The images I processed had dimensions 512x512x166, with each pixel being a 32-b...
Opengraph URL: https://github.com/python-humanize/humanize/issues/217
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"naturalsize np.int32 multiplication overflow","articleBody":"### What did you do?\r\n\r\nI was using the torchio library, which relies on humanize to return the memory size of image arrays. The images I processed had dimensions 512x512x166, with each pixel being a 32-bit (4-byte) integer.\r\n### What did you expect to happen?\r\n\r\ntorchio calls the naturalsize function with the occupied memory size in bytes and sets binary=True. Manually calculating the expected value:\r\n512×512×166×4÷(1024×1024)=166 MiB\r\n\r\nSo, I expected the function to return approximately 166 MiB.\r\n### What actually happened?\r\n\r\nInstead, the returned value was -2 MiB, accompanied by this warning:\r\n```\r\nRuntimeWarning: overflow encountered in scalar multiply\r\nret: str = format % ((base * bytes_ / unit)) + s\r\n``` \r\n\r\nThis overflow occurs because the input to the function was of type np.int32 instead of Python's native int. Since np.int32 has a maximum value of 2^31−1, the multiplication of base and bytes_ results in an overflow.\r\n### Steps to Reproduce\r\n\r\n```python\r\n\r\nimport humanize\r\nimport numpy as np\r\n\r\nprint(humanize.naturalsize(512*512*166*4, binary=True)) \r\n# Expected: 166.0 MiB\r\n# Works as expected with Python’s built-in int type\r\n\r\nprint(humanize.naturalsize(np.int32(512*512*166*4), binary=True))\r\n# Returns: -2.0 MiB\r\n# RuntimeWarning: overflow encountered in scalar multiply ret: str = format % ((base * bytes_ / unit)) + s\r\n```\r\n\r\n### Proposed Solutions\r\n\r\n1) Change the Order of Operations\r\nAdjusting the order of operations can avoid overflow. In the current line:\r\n\r\n```python\r\n\r\nret: str = format % ((base * bytes_ / unit)) + s\r\n```\r\n\r\nwhen bytes_ is np.int32, multiplying base and bytes_ produces an np.int32 result, which overflows before it’s divided by unit. By dividing either base or bytes_ by unit before the multiplication, each sub-operation remains a float:\r\n\r\n```python\r\n\r\nret: str = format % ((base * (bytes_ / unit))) + s\r\n# or\r\nret: str = format % ((base / unit * bytes_)) + s\r\n```\r\n2) Convert Input to Float\r\n Alternatively, cast value to float without checking its type. Currently, the casting applies only if value is a string:\r\n\r\n```python\r\n\r\n# Current approach\r\nif isinstance(value, str):\r\n bytes_ = float(value)\r\nelse:\r\n bytes_ = value\r\n```\r\nUpdating it to cast all inputs to float could resolve the issue:\r\n\r\n```python\r\n\r\nbytes_ = float(value)\r\n```\r\nI haven’t created a pull request since I’m unsure if you’d prefer developers to ensure input compatibility or handle this within the function.\r\nEnvironment\r\n\r\n OS: Windows 11\r\n Python: 3.12.1\r\n Humanize: 4.11.0\r\n Numpy: 1.26.3","author":{"url":"https://github.com/Toprak2","@type":"Person","name":"Toprak2"},"datePublished":"2024-11-05T19:01:52.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":3},"url":"https://github.com/217/humanize/issues/217"}
| 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:13aec007-6344-dd3a-efdb-3ae8cf788c68 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | A450:17CF54:19D96D8:235625C:6A53F320 |
| html-safe-nonce | c0356272cb52be5c3b31ebcf7d93bfa0a3d7c17f0be38f159f82d2e59ff3973f |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBNDUwOjE3Q0Y1NDoxOUQ5NkQ4OjIzNTYyNUM6NkE1M0YzMjAiLCJ2aXNpdG9yX2lkIjoiMzc5MDUxNzE4MjY0MDk0MzkwNCIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 3d69d24ddb2f09b59a10406ac1898ce6f2980e93c06b869b89c516f80d563267 |
| hovercard-subject-tag | issue:2636242617 |
| 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-humanize/humanize/217/issue_layout |
| twitter:image | https://opengraph.githubassets.com/48792eca6342827ef45246ec9b7cd73d789e73ccb71a4cd17f22939e06c60171/python-humanize/humanize/issues/217 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/48792eca6342827ef45246ec9b7cd73d789e73ccb71a4cd17f22939e06c60171/python-humanize/humanize/issues/217 |
| og:image:alt | What did you do? I was using the torchio library, which relies on humanize to return the memory size of image arrays. The images I processed had dimensions 512x512x166, with each pixel being a 32-b... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | Toprak2 |
| hostname | github.com |
| expected-hostname | github.com |
| None | b9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb |
| turbo-cache-control | no-preview |
| go-import | github.com/python-humanize/humanize git https://github.com/python-humanize/humanize.git |
| octolytics-dimension-user_id | 62149795 |
| octolytics-dimension-user_login | python-humanize |
| octolytics-dimension-repository_id | 466683324 |
| octolytics-dimension-repository_nwo | python-humanize/humanize |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 466683324 |
| octolytics-dimension-repository_network_root_nwo | python-humanize/humanize |
| 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 | 07a982c1d40157c619b364352b704c3ce66bb332 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width