├── .github └── FUNDING.yml ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── numerize ├── __init__.py ├── numerize.py └── test.py └── setup.py /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: davidsa03 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "3.2" 5 | - "3.3" 6 | - "3.6" 7 | # command to install dependencies 8 | install: 9 | - pip install . 10 | script: python numerize/test.py 11 | branches: 12 | only: 13 | - master 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this numerize, please write easy and clear changes you wish to make by forking and pull 4 | request. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 17 | ## Code of Conduct 18 | 19 | ### Our Pledge 20 | 21 | In the interest of fostering an open and welcoming environment, we as 22 | contributors and maintainers pledge to making participation in our project and 23 | our community a harassment-free experience for everyone, regardless of age, body 24 | size, disability, ethnicity, gender identity and expression, level of experience, 25 | nationality, personal appearance, race, religion, or sexual identity and 26 | orientation. 27 | 28 | ### Our Standards 29 | 30 | Examples of behavior that contributes to creating a positive environment 31 | include: 32 | 33 | * Using welcoming and inclusive language 34 | * Being respectful of differing viewpoints and experiences 35 | * Gracefully accepting constructive criticism 36 | * Focusing on what is best for the community 37 | * Showing empathy towards other community members 38 | 39 | Examples of unacceptable behavior by participants include: 40 | 41 | * The use of sexualized language or imagery and unwelcome sexual attention or 42 | advances 43 | * Trolling, insulting/derogatory comments, and personal or political attacks 44 | * Public or private harassment 45 | * Publishing others' private information, such as a physical or electronic 46 | address, without explicit permission 47 | * Other conduct which could reasonably be considered inappropriate in a 48 | professional setting 49 | 50 | ### Our Responsibilities 51 | 52 | Project maintainers are responsible for clarifying the standards of acceptable 53 | behavior and are expected to take appropriate and fair corrective action in 54 | response to any instances of unacceptable behavior. 55 | 56 | Project maintainers have the right and responsibility to remove, edit, or 57 | reject comments, commits, code, wiki edits, issues, and other contributions 58 | that are not aligned to this Code of Conduct, or to ban temporarily or 59 | permanently any contributor for other behaviors that they deem inappropriate, 60 | threatening, offensive, or harmful. 61 | 62 | ### Scope 63 | 64 | This Code of Conduct applies both within project spaces and in public spaces 65 | when an individual is representing the project or its community. Examples of 66 | representing a project or community include using an official project e-mail 67 | address, posting via an official social media account, or acting as an appointed 68 | representative at an online or offline event. Representation of a project may be 69 | further defined and clarified by project maintainers. 70 | 71 | ### Enforcement 72 | 73 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 74 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All 75 | complaints will be reviewed and investigated and will result in a response that 76 | is deemed necessary and appropriate to the circumstances. The project team is 77 | obligated to maintain confidentiality with regard to the reporter of an incident. 78 | Further details of specific enforcement policies may be posted separately. 79 | 80 | Project maintainers who do not follow or enforce the Code of Conduct in good 81 | faith may face temporary or permanent repercussions as determined by other 82 | members of the project's leadership. 83 | 84 | ### Attribution 85 | 86 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 87 | available at [http://contributor-covenant.org/version/1/4][version] 88 | 89 | [homepage]: http://contributor-covenant.org 90 | [version]: http://contributor-covenant.org/version/1/4/ 91 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 David Sa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/davidsa03/numerize.svg?branch=master)](https://travis-ci.org/davidsa03/numerize) 2 | ![Python 2.7](https://img.shields.io/badge/python-2.7-green.svg) 3 | ![Python 3.6](https://img.shields.io/badge/python-3.6-green.svg) 4 | [![license](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000)](https://github.com/davidsa03/numerize/blob/master/LICENSE) 5 | # Numerize 6 | 7 | Numerize is a Python (2 and 3) library for converting large numbers into readable strings. 8 | Similar to what Twitter and Instagram use for large follower counts. 9 | 10 | | Number | Numerized | 11 | |------|:---------:| 12 | | 1 | **1** | 13 | | 1000 | **1K** | 14 | | 1500 | **1.5K** | 15 | | 1000000 | **1M** | 16 | | 1500000 | **1.5M** | 17 | | 1000000000 | **1B** | 18 | | 1500000000 | **1.5B** | 19 | | 1000000000000 | **1T** | 20 | | 1500000000000 | **1.5T** | 21 | | 21324314 | **21.32M**| 22 | | -21324314 | **-21.32M**| 23 | 24 | ## Installation 25 | 26 | ``` 27 | $ pip install numerize 28 | ``` 29 | 30 | ## Usage 31 | 32 | numerize(number_to_numerize, decimal_places_to_round[optional]) 33 | 34 | ``` 35 | >>> from numerize.numerize import numerize 36 | >>> numerize(1234567.12) 37 | '1.23M' 38 | >>> numerize(12134.123, 3) 39 | '12.134K' 40 | ``` 41 | This will convert large numbers like 1234567.12 into 1.23M 42 | 43 | ## Requirements 44 | - Python >= 2.7 or >= 3.4 45 | 46 | ## Contributing 47 | [How to contribute](https://github.com/davidsa03/numerize/blob/master/CONTRIBUTING.md) 48 | 49 | ## Testing 50 | 51 | ``` 52 | $ python numerize/test.py 53 | ``` 54 | 55 | ## License 56 | MIT licensed. 57 | -------------------------------------------------------------------------------- /numerize/__init__.py: -------------------------------------------------------------------------------- 1 | from numerize import * 2 | -------------------------------------------------------------------------------- /numerize/numerize.py: -------------------------------------------------------------------------------- 1 | from decimal import Decimal 2 | 3 | def round_num(n, decimal=2): 4 | n=Decimal(n) 5 | return n.to_integral() if n == n.to_integral() else round(n.normalize(), decimal) 6 | 7 | def numerize(n, decimal=2): 8 | #60 sufixes 9 | sufixes = [ "", "K", "M", "B", "T", "Qa", "Qu", "S", "Oc", "No", 10 | "D", "Ud", "Dd", "Td", "Qt", "Qi", "Se", "Od", "Nd","V", 11 | "Uv", "Dv", "Tv", "Qv", "Qx", "Sx", "Ox", "Nx", "Tn", "Qa", 12 | "Qu", "S", "Oc", "No", "D", "Ud", "Dd", "Td", "Qt", "Qi", 13 | "Se", "Od", "Nd", "V", "Uv", "Dv", "Tv", "Qv", "Qx", "Sx", 14 | "Ox", "Nx", "Tn", "x", "xx", "xxx", "X", "XX", "XXX", "END"] 15 | 16 | sci_expr = [1e0, 1e3, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24, 1e27, 17 | 1e30, 1e33, 1e36, 1e39, 1e42, 1e45, 1e48, 1e51, 1e54, 1e57, 18 | 1e60, 1e63, 1e66, 1e69, 1e72, 1e75, 1e78, 1e81, 1e84, 1e87, 19 | 1e90, 1e93, 1e96, 1e99, 1e102, 1e105, 1e108, 1e111, 1e114, 1e117, 20 | 1e120, 1e123, 1e126, 1e129, 1e132, 1e135, 1e138, 1e141, 1e144, 1e147, 21 | 1e150, 1e153, 1e156, 1e159, 1e162, 1e165, 1e168, 1e171, 1e174, 1e177] 22 | minus_buff = n 23 | n=abs(n) 24 | for x in range(len(sci_expr)): 25 | try: 26 | if n >= sci_expr[x] and n < sci_expr[x+1]: 27 | sufix = sufixes[x] 28 | if n >= 1e3: 29 | num = str(round_num(n/sci_expr[x], decimal)) 30 | else: 31 | num = str(n) 32 | return num + sufix if minus_buff > 0 else "-" + num + sufix 33 | except IndexError: 34 | print("You've reached the end") 35 | 36 | 37 | def denumerize(n): 38 | try: 39 | 40 | sufixes = [ "", "K", "M", "B", "T", "Qa", "Qu", "S", "Oc", "No", 41 | "D", "Ud", "Dd", "Td", "Qt", "Qi", "Se", "Od", "Nd","V", 42 | "Uv", "Dv", "Tv", "Qv", "Qx", "Sx", "Ox", "Nx", "Tn", "Qa", 43 | "Qu", "S", "Oc", "No", "D", "Ud", "Dd", "Td", "Qt", "Qi", 44 | "Se", "Od", "Nd", "V", "Uv", "Dv", "Tv", "Qv", "Qx", "Sx", 45 | "Ox", "Nx", "Tn", "x", "xx", "xxx", "X", "XX", "XXX", "END"] 46 | 47 | sci_expr = [1e0, 1e3, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24, 1e27, 48 | 1e30, 1e33, 1e36, 1e39, 1e42, 1e45, 1e48, 1e51, 1e54, 1e57, 49 | 1e60, 1e63, 1e66, 1e69, 1e72, 1e75, 1e78, 1e81, 1e84, 1e87, 50 | 1e90, 1e93, 1e96, 1e99, 1e102, 1e105, 1e108, 1e111, 1e114, 1e117, 51 | 1e120, 1e123, 1e126, 1e129, 1e132, 1e135, 1e138, 1e141, 1e144, 1e147, 52 | 1e150, 1e153, 1e156, 1e159, 1e162, 1e165, 1e168, 1e171, 1e174, 1e177] 53 | 54 | suffix_idx = 0 55 | 56 | for i in n: 57 | if type(i) != int: 58 | suffix_idx = n.index(i) 59 | 60 | 61 | suffix = n[suffix_idx:] 62 | num = n[:suffix_idx] 63 | 64 | suffix_val = sci_expr[sufixes.index(suffix)] 65 | 66 | result = int(num) * suffix_val 67 | 68 | return result 69 | 70 | except: 71 | return 'err' 72 | -------------------------------------------------------------------------------- /numerize/test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from numerize import numerize 3 | class TestNumerizeFunc(unittest.TestCase): 4 | def test_numerize(self): 5 | self.assertEqual(numerize(1), "1") 6 | self.assertEqual(numerize(10), "10") 7 | def test_thousand(self): 8 | self.assertEqual(numerize(1000), "1K") 9 | def test_strict(self): 10 | self.assertEqual(numerize(999), "999") 11 | self.assertEqual(numerize(9999), "10.00K") 12 | def test_negative(self): 13 | self.assertEqual(numerize(-1), "-1") 14 | self.assertEqual(numerize(-10), "-10") 15 | self.assertEqual(numerize(-1000), "-1K") 16 | self.assertEqual(numerize(-9999,4), "-9.9990K") 17 | 18 | if __name__ == '__main__': 19 | unittest.main() -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | try: 4 | import pypandoc 5 | long_description = pypandoc.convert('README.md', 'rst') 6 | except(IOError, ImportError): 7 | long_description = open('README.md').read() 8 | 9 | setup( 10 | name='numerize', 11 | version='0.13', 12 | description='Convert large numbers into readable numbers for humans.', 13 | long_description=long_description, 14 | long_description_content_type='text/markdown', 15 | author='David Sa', 16 | author_email='davidsa03@gmail.com', 17 | packages=['numerize'], #same as name 18 | url='https://github.com/davidsa03/numerize', 19 | license='MIT', 20 | install_requires=[ 21 | # -*- Extra requirements: -*- 22 | ], 23 | ) 24 | --------------------------------------------------------------------------------