{"id":13490728,"url":"https://github.com/SethMMorton/fastnumbers","last_synced_at":"2025-03-28T07:31:26.249Z","repository":{"id":19383992,"uuid":"22624904","full_name":"SethMMorton/fastnumbers","owner":"SethMMorton","description":"Super-fast and clean conversions to numbers for Python.","archived":false,"fork":false,"pushed_at":"2024-10-24T02:21:38.000Z","size":1578,"stargazers_count":105,"open_issues_count":2,"forks_count":13,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-10-24T21:53:45.941Z","etag":null,"topics":["c-extension","conversion","numbers","optimization","python","utility","utility-library"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/fastnumbers/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SethMMorton.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-08-05T00:44:53.000Z","updated_at":"2024-10-14T17:14:55.000Z","dependencies_parsed_at":"2024-06-18T18:11:16.506Z","dependency_job_id":"73dc662e-7f4d-421b-a57c-b962b0379115","html_url":"https://github.com/SethMMorton/fastnumbers","commit_stats":{"total_commits":758,"total_committers":5,"mean_commits":151.6,"dds":0.00527704485488123,"last_synced_commit":"50dee124f232422a66bcc603b43216bf7a94e587"},"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SethMMorton%2Ffastnumbers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SethMMorton%2Ffastnumbers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SethMMorton%2Ffastnumbers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SethMMorton%2Ffastnumbers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SethMMorton","download_url":"https://codeload.github.com/SethMMorton/fastnumbers/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245989053,"owners_count":20705744,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-extension","conversion","numbers","optimization","python","utility","utility-library"],"created_at":"2024-07-31T19:00:50.424Z","updated_at":"2025-03-28T07:31:25.730Z","avatar_url":"https://github.com/SethMMorton.png","language":"C++","readme":"fastnumbers\n===========\n\n.. image:: https://img.shields.io/pypi/v/fastnumbers.svg\n    :target: https://pypi.org/project/fastnumbers/\n\n.. image:: https://img.shields.io/pypi/pyversions/fastnumbers.svg\n    :target: https://pypi.org/project/fastnumbers/\n\n.. image:: https://img.shields.io/pypi/l/fastnumbers.svg\n    :target: https://github.com/SethMMorton/fastnumbers/blob/main/LICENSE\n\n.. image:: https://github.com/SethMMorton/fastnumbers/workflows/Tests/badge.svg\n    :target: https://github.com/SethMMorton/fastnumbers/actions\n\n.. image:: https://codecov.io/gh/SethMMorton/fastnumbers/branch/main/graph/badge.svg\n    :target: https://codecov.io/gh/SethMMorton/fastnumbers\n\n.. image:: https://img.shields.io/pypi/dw/fastnumbers.svg\n    :target: https://pypi.org/project/fastnumbers/\n\nSuper-fast and clean conversions to numbers.\n\n    - Source Code: https://github.com/SethMMorton/fastnumbers\n    - Downloads: https://pypi.org/project/fastnumbers/\n    - Documentation: https://fastnumbers.readthedocs.io/\n    - `Quick Start`_\n    - `Timing`_\n    - `High-level Algorithm`_\n    - `How To Run Tests`_\n    - `History`_\n\n``fastnumbers`` is a module with the following three objectives (in order\nof decreasing importance as to why the module was created):\n\n    #. Provide a set of convenience functions that wrap calls to\n       ``int`` and ``float`` and provides easy, concise, powerful, fast\n       and flexible error handling.\n    #. Provide a set of functions that can be used to rapidly identify if\n       an input *could* be converted to *int* or *float*.\n    #. Provide drop-in replacements for the Python built-in ``int`` and\n       ``float`` that are on par or faster with the Python equivalents\n       (see the `Timing`_ section for details). These functions\n       should behave *identically* to the Python built-ins except for a few\n       specific corner-cases as mentioned in the\n       `API documentation for those functions \u003chttps://fastnumbers.readthedocs.io/en/stable/api.html#the-built-in-replacement-functions\u003e`_.\n\n       - **PLEASE** read the quick start for these functions to fully\n         understand the caveats before using them.\n\n**What kind of speedups can you expect?** Here are some highlights, but please\nsee the `Timing`_ section for the raw data if you want details.\n\n    - Up to 2x faster conversion of strings to integers than the built-in\n      ``int()`` function\n    - Up to 5x faster conversion of strings to floats than the built-in\n      ``float()`` function (possibly greater for very long strings)\n    - Up to 10x faster handling of errors during conversion than using\n      user-side error handling\n    - On top of the above, operations to convert a list of strings\n      (with the ``map`` option or ``try_array`` function) is 2x faster\n      than the equivalent list comprehension.\n\n**NOTICE**: As of ``fastnumbers`` version 4.0.0, only Python \u003e= 3.7 is\nsupported.\n\n**NOTICE**: As of ``fastnumbers`` version 4.0.0, the functions ``fast_real``,\n``fast_float``, ``fast_int``, ``fast_forceint``, ``isreal``, ``isfloat``,\n``isint``, and ``isintlike`` have been deprecated and are replaced with\n``try_real``, ``try_float``, ``try_int``, ``try_forceint``, ``check_real``,\n``check_float``, ``check_int``, and ``check_intlike``, respectively. These\nnew functions have more flexible APIs and have names that better reflect\nthe intent of the functions. The old functions can still be used (they will\n*never* be removed from ``fastnumbers``), but the new ones should be\npreferred for new development.\n\n**NOTICE**: As of ``fastnumbers`` version 4.0.0, ``query_type`` now sets\n``allow_underscores`` to ``False`` by default instead of ``True``.\n\nQuick Start\n-----------\n\n- `Error-handling Functions`_\n- `Checking Functions`_\n- `Drop-in Replacement Functions`_\n\nThere are three broad categories of functions exposed by ``fastnumbers``.\nThe below quick start will demonstrate each of these categories. The\nquick start is \"by example\", and will show a sample interactive session\nusing the ``fastnumbers`` API.\n\nError-Handling Functions\n++++++++++++++++++++++++\n\n- `Error-handling function API \u003chttps://fastnumbers.readthedocs.io/en/stable/api.html#the-error-handling-functions\u003e`_\n- `Fast operations on lists and other iterables`_\n- `About the on_fail option`_\n- `About the denoise option`_\n\n``try_float`` will be used to demonstrate the functionality of the\n``try_*`` functions.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import RAISE, try_float\n    \u003e\u003e\u003e # Convert string to a float\n    \u003e\u003e\u003e try_float('56.07')\n    56.07\n    \u003e\u003e\u003e # Integers are converted to floats\n    \u003e\u003e\u003e try_float(54)\n    54.0\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # Unconvertable string returned as-is by default\n    \u003e\u003e\u003e try_float('bad input')\n    'bad input'\n    \u003e\u003e\u003e # Unconvertable strings can trigger a default value\n    \u003e\u003e\u003e try_float('bad input', on_fail=0)\n    0\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # One can ask inf or nan to be substituted with another value\n    \u003e\u003e\u003e try_float('nan')\n    nan\n    \u003e\u003e\u003e try_float('nan', nan=0.0)\n    0.0\n    \u003e\u003e\u003e try_float(float('nan'), nan=0.0)\n    0.0\n    \u003e\u003e\u003e try_float('56.07', nan=0.0)\n    56.07\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # The default built-in float behavior can be triggered with\n    \u003e\u003e\u003e # RAISE given to \"on_fail\".\n    \u003e\u003e\u003e try_float('bad input', on_fail=RAISE) #doctest: +IGNORE_EXCEPTION_DETAIL\n    Traceback (most recent call last):\n      ...\n    ValueError: invalid literal for float(): bad input\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # A function can be used to return an alternate value for invalid input\n    \u003e\u003e\u003e try_float('bad input', on_fail=len)\n    9\n    \u003e\u003e\u003e try_float(54, on_fail=len)\n    54.0\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # Single unicode characters can be converted.\n    \u003e\u003e\u003e try_float('\\u2164')  # Roman numeral 5 (V)\n    5.0\n    \u003e\u003e\u003e try_float('\\u2466')  # 7 enclosed in a circle\n    7.0\n\n``try_int`` behaves the same as ``try_float``, but for integers.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import try_int\n    \u003e\u003e\u003e try_int('1234')\n    1234\n    \u003e\u003e\u003e try_int('\\u2466')\n    7\n\n``try_real`` is like ``try_float`` or ``try_int`` depending\non if there is any fractional component of thi return value.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import try_real\n    \u003e\u003e\u003e try_real('56')\n    56\n    \u003e\u003e\u003e try_real('56.0')\n    56\n    \u003e\u003e\u003e try_real('56.0', coerce=False)\n    56.0\n    \u003e\u003e\u003e try_real('56.07')\n    56.07\n    \u003e\u003e\u003e try_real(56.07)\n    56.07\n    \u003e\u003e\u003e try_real(56.0)\n    56\n    \u003e\u003e\u003e try_real(56.0, coerce=False)\n    56.0\n\n``try_forceint`` always returns an integer.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import try_forceint\n    \u003e\u003e\u003e try_forceint('56')\n    56\n    \u003e\u003e\u003e try_forceint('56.0')\n    56\n    \u003e\u003e\u003e try_forceint('56.07')\n    56\n    \u003e\u003e\u003e try_forceint(56.07)\n    56\n\nFast operations on lists and other iterables\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nEach of the ``try_*`` functions have a ``map`` option causes the function\nto accept an iterable of items to convert and returns a list. Using\n``try_float`` as an example, the following are all functionally equivalent.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import try_float\n    \u003e\u003e\u003e iterable = [\"5\", \"4.5\", \"34567.6\", \"32\"]\n    \u003e\u003e\u003e try_float(iterable, map=list) == list(map(try_float, iterable))\n    True\n    \u003e\u003e\u003e try_float(iterable, map=list) == [try_float(x) for x in iterable]\n    True\n    \u003e\u003e\u003e try_float(iterable, map=list) == list(try_float(iterable, map=True))\n    True\n\nThe difference is that the ``map`` option is 2x the speed of the list\ncomprehension method, and 1.5x the speed of the ``map`` method. The reason\nis that it avoids Python function call overhead on each iteration. Note that\n*True* causes the function to return an iterator, and *list* causes it to\nreturn a ``list``. In practice the performance of these are similar\n(see `Timing`_ for raw data).\n\nIf you need to store your output in a ``numpy`` array, you can use\n``try_array`` to do this conversion directly. This function has some\nadditional handling for overflow that is not present in the other\n``fastnumbers`` functions that may come in handy when dealing with\n``numpy`` arrays.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import try_array\n    \u003e\u003e\u003e import numpy as np\n    \u003e\u003e\u003e iterable = [\"5\", \"4.5\", \"34567.6\", \"32\"]\n    \u003e\u003e\u003e np.array_equal(np.array(try_float(iterable, map=list), dtype=np.float64), try_array(iterable))\n    True\n\nYou will see about a 2x speedup of doing this in one step over converting\nto a list then converting that list to an array.\n\nAbout the ``on_fail`` option\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nThe ``on_fail`` option is a way for you to do *anything* in the event that\nthe given input cannot be converted to a number. It can\n\n* return given object as-is if set to ``fastnumbers.INPUT`` (this is the default)\n* raise a ``ValueError`` if set to ``fastnumbers.RAISE``\n* return a default value if given any non-callable object\n* call a function with the given object if given a single-argument callable\n\nBelow are a couple of ideas to get you thinking.\n\n**NOTE**:: There is also an ``on_type_error`` option that behaves the same as\n``on_fail`` except that a) it is triggered when the given object is of an\ninvalid type and b) the default value is ``fastnumbers.RAISE``, not\n``fastnumbers.INPUT``.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import INPUT, RAISE, try_float\n    \u003e\u003e\u003e # You want to convert strings that can be converted to numbers, but\n    \u003e\u003e\u003e # leave the rest as strings. Use fastnumbers.INPUT (the default)\n    \u003e\u003e\u003e try_float('45.6')\n    45.6\n    \u003e\u003e\u003e try_float('invalid input')\n    'invalid input'\n    \u003e\u003e\u003e try_float('invalid input', on_fail=INPUT)\n    'invalid input'\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # You want to convert any invalid string to NaN\n    \u003e\u003e\u003e try_float('45.6', on_fail=float('nan'))\n    45.6\n    \u003e\u003e\u003e try_float('invalid input', on_fail=float('nan'))\n    nan\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # Simple callable case, send the input through some function to generate a number.\n    \u003e\u003e\u003e try_float('invalid input', on_fail=lambda x: float(x.count('i')))  # count the 'i's\n    3.0\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # Suppose we know that our input could either be a number, or if not\n    \u003e\u003e\u003e # then we know we just have to strip off parens to get to the number\n    \u003e\u003e\u003e # e.g. the input could be '45' or '(45)'. Also, suppose that if it\n    \u003e\u003e\u003e # still cannot be converted to a number we want to raise an exception.\n    \u003e\u003e\u003e def strip_parens_and_try_again(x):\n    ...     return try_float(x.strip('()'), on_fail=RAISE)\n    ...\n    \u003e\u003e\u003e try_float('45', on_fail=strip_parens_and_try_again)\n    45.0\n    \u003e\u003e\u003e try_float('(45)', on_fail=strip_parens_and_try_again)\n    45.0\n    \u003e\u003e\u003e try_float('invalid input', on_fail=strip_parens_and_try_again) #doctest: +IGNORE_EXCEPTION_DETAIL\n    Traceback (most recent call last):\n      ...\n    ValueError: invalid literal for float(): invalid input\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # Suppose that whenever an invalid input is given, it needs to be\n    \u003e\u003e\u003e # logged and then a default value is returned.\n    \u003e\u003e\u003e def log_and_default(x, log_method=print, default=0.0):\n    ...     log_method(\"The input {!r} is not valid!\".format(x))\n    ...     return default\n    ...\n    \u003e\u003e\u003e try_float('45', on_fail=log_and_default)\n    45.0\n    \u003e\u003e\u003e try_float('invalid input', on_fail=log_and_default)\n    The input 'invalid input' is not valid!\n    0.0\n    \u003e\u003e\u003e try_float('invalid input', on_fail=lambda x: log_and_default(x, default=float('nan')))\n    The input 'invalid input' is not valid!\n    nan\n\nAbout the ``denoise`` option\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nThe ``denoise`` option is available on the ``try_real`` and ``try_forceint`` options.\nTo best understand its usage, consider the following native Python behavior:\n\n.. code-block:: python\n\n    \u003e\u003e\u003e int(3.453e21)\n    3452999999999999737856\n    \u003e\u003e\u003e int(float(\"3.453e21\"))\n    3452999999999999737856\n    \u003e\u003e\u003e # Most users would likely expect this result from decimal.Decimal\n    \u003e\u003e\u003e import decimal\n    \u003e\u003e\u003e int(decimal.Decimal(\"3.453e21\"))\n    3453000000000000000000\n    \u003e\u003e\u003e # But watch out, even decimal.Decimal doesn't help for float input\n    \u003e\u003e\u003e import decimal\n    \u003e\u003e\u003e int(decimal.Decimal(3.453e21))\n    3452999999999999737856\n\nBecause the conversion of a float to an int goes through the C ``double`` data type which\nhas inherent limitations on accuracy (See\n`this Stack Overflow question for examples \u003chttps://stackoverflow.com/questions/588004/is-floating-point-math-broken\u003e`_)\nthe resulting ``int`` result has \"noise\" digits that are not part of the original float\nrepresentation.\n\nFor functions where this makes sense, ``fastnumbers`` provides the ``denoise`` option to\ngive you the results that ``decimal.Decimal`` would give for strings containing floats.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import try_real\n    \u003e\u003e\u003e try_real(3.453e21)\n    3452999999999999737856\n    \u003e\u003e\u003e try_real(\"3.453e21\")\n    3452999999999999737856\n    \u003e\u003e\u003e try_real(3.453e21, denoise=True)\n    3453000000000000000000\n    \u003e\u003e\u003e try_real(\"3.453e21\", denoise=True)\n    3453000000000000000000\n\nTwo things to keep in mind:\n\n1. The ``denoise`` option adds additional overhead to the conversion calculation, so please consider\n   the trade-offs between speed and accuracy when determining whether or not to use it. It is\n   *significantly* faster than using ``decimal.Decimal``, but much slower than not using it at all.\n2. For string input, ``denoise`` will return results identical to ``decimal.Decimal``. For float\n   input, ``denoise`` will return results that are accurate to about 15 digits (C ``double`` can\n   only store 16 decimal digits, so this means that only the last possible digit may not be accurate).\n\nChecking Functions\n++++++++++++++++++\n\n- `Checking function API \u003chttps://fastnumbers.readthedocs.io/en/stable/api.html#the-checking-functions\u003e`_\n\n``check_float`` will be used to demonstrate the functionality of the\n``check_*`` functions. There is also the ``query_type`` function.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import check_float\n    \u003e\u003e\u003e from fastnumbers import ALLOWED, DISALLOWED, NUMBER_ONLY, STRING_ONLY\n    \u003e\u003e\u003e # Check that a string can be converted to a float\n    \u003e\u003e\u003e check_float('56')\n    True\n    \u003e\u003e\u003e check_float('56', strict=True)\n    False\n    \u003e\u003e\u003e check_float('56.07')\n    True\n    \u003e\u003e\u003e check_float('56.07 lb')\n    False\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # Check if a given number is a float\n    \u003e\u003e\u003e check_float(56.07)\n    True\n    \u003e\u003e\u003e check_float(56)\n    False\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # Specify if only strings or only numbers are allowed\n    \u003e\u003e\u003e check_float(56.07, consider=STRING_ONLY)\n    False\n    \u003e\u003e\u003e check_float('56.07', consider=NUMBER_ONLY)\n    False\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e # Customize handling for nan or inf (see API for more details)\n    \u003e\u003e\u003e check_float('nan')\n    False\n    \u003e\u003e\u003e check_float('nan', nan=ALLOWED)\n    True\n    \u003e\u003e\u003e check_float(float('nan'))\n    True\n    \u003e\u003e\u003e check_float(float('nan'), nan=DISALLOWED)\n    False\n\n``check_int`` works the same as ``check_float``, but for integers.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import check_int\n    \u003e\u003e\u003e check_int('56')\n    True\n    \u003e\u003e\u003e check_int(56)\n    True\n    \u003e\u003e\u003e check_int('56.0')\n    False\n    \u003e\u003e\u003e check_int(56.0)\n    False\n\n``check_real`` is very permissive - any float or integer is accepted.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import check_real\n    \u003e\u003e\u003e check_real('56.0')\n    True\n    \u003e\u003e\u003e check_real('56')\n    True\n    \u003e\u003e\u003e check_real(56.0)\n    True\n    \u003e\u003e\u003e check_real(56)\n    True\n\n``check_intlike`` checks if a number is \"int-like\", if it has no\nfractional component.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import check_intlike\n    \u003e\u003e\u003e check_intlike('56.0')\n    True\n    \u003e\u003e\u003e check_intlike('56.7')\n    False\n    \u003e\u003e\u003e check_intlike(56.0)\n    True\n    \u003e\u003e\u003e check_intlike(56.7)\n    False\n\nThe ``query_type`` function can be used if you need to determine if\na value is one of many types, rather than whether or not it is one specific\ntype.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import query_type\n    \u003e\u003e\u003e query_type('56.0')\n    \u003cclass 'float'\u003e\n    \u003e\u003e\u003e query_type('56')\n    \u003cclass 'int'\u003e\n    \u003e\u003e\u003e query_type(56.0)\n    \u003cclass 'float'\u003e\n    \u003e\u003e\u003e query_type(56)\n    \u003cclass 'int'\u003e\n    \u003e\u003e\u003e query_type(56.0, coerce=True)\n    \u003cclass 'int'\u003e\n    \u003e\u003e\u003e query_type('56.0', allowed_types=(float, int))\n    \u003cclass 'float'\u003e\n    \u003e\u003e\u003e query_type('hey')\n    \u003cclass 'str'\u003e\n    \u003e\u003e\u003e query_type('hey', allowed_types=(float, int))  # returns None\n\nDrop-in Replacement Functions\n+++++++++++++++++++++++++++++\n\n- `Drop-in replacement function API \u003chttps://fastnumbers.readthedocs.io/en/stable/api.html#the-built-in-replacement-functions\u003e`_\n\n**PLEASE** do not take it for granted that these functions will provide you\nwith a speedup - they may not. Every platform, compiler, and data-set is\ndifferent, and you should perform a timing test on your system with your data\nto evaluate if you will see a benefit. As you can see from the data linked in\nthe `Timing`_ section, the amount of speedup you will get is particularly\ndata-dependent. *In general* you will see a performance boost for floats (and\nthis boost increases as the size of the float increases), but for integers it\nis largely dependent on the length of the integer. You will likely *not* see\na performance boost if the input are already numbers instead of strings.\n\n**NOTE**: in the below examples, we use ``from fastnumbers import int`` instead\nof ``import fastnumbers``. This is because calling ``fastnumbers.int()`` is a\nbit slower than just ``int()`` because Python has to first find ``fastnumbers``\nin your namespace, then find ``int`` in the ``fastnumbers`` namespace, instead\nof just finding ``int`` in your namespace - this will slow down the function\ncall and defeat the purpose of using ``fastnumbers``. If you do not want to\nactually shadow the built-in ``int`` function, you can do\n``from fastnumbers import int as fn_int`` or something like that.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e # Use is identical to the built-in functions\n    \u003e\u003e\u003e from fastnumbers import float, int\n    \u003e\u003e\u003e float('10')\n    10.0\n    \u003e\u003e\u003e int('10')\n    10\n    \u003e\u003e\u003e float('bad input') #doctest: +IGNORE_EXCEPTION_DETAIL\n    Traceback (most recent call last):\n      ...\n    ValueError: invalid literal for float(): bad input\n\n``real`` is provided to give a float or int depending\non the fractional component of the input.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from fastnumbers import real\n    \u003e\u003e\u003e real('56.0')\n    56\n    \u003e\u003e\u003e real('56.7')\n    56.7\n    \u003e\u003e\u003e real('56.0', coerce=False)\n    56.0\n\nTiming\n------\n\nJust how much faster is ``fastnumbers`` than a pure python implementation?\nPlease look https://github.com/SethMMorton/fastnumbers/tree/main/profiling.\n\nHigh-Level Algorithm\n--------------------\n\nFor integers, CPython goes to great lengths to ensure that your string input\nis converted to a number *correctly* and *losslessly* (you can prove this to\nyourself by examining the source code for\n`integer conversions \u003chttps://github.com/python/cpython/blob/e349bf23584eef20e0d1e1b2989d9b1430f15507/Objects/longobject.c#L2213\u003e`_).\nThis extra effort is only needed for integers that cannot fit into a 64-bit\ninteger data type - for those that can, a naive algorithm of \u003c 10 lines\nof C code is sufficient and significantly faster. ``fastnumbers`` uses a\nheuristic to determine if the input can be safely converted with the much\nfaster naive algorithm, and if so it does so, falling back on\nthe CPython implementation for longer input strings.\nMost real-world numbers pass the heuristic and so you should generally see\nimproved performance with ``fastnumbers`` for integers.\n\nFor floats, ``fastnumbers`` utilizes the ultra-fast\n`fast_float::from_chars \u003chttps://github.com/fastfloat/fast_float\u003e`_ function\nto convert strings representing floats into a C ``double`` both quickly *and\nsafely* - the conversion provides the same accuracy as the CPython\n`float conversion function \u003chttps://github.com/python/cpython/blob/e349bf23584eef20e0d1e1b2989d9b1430f15507/Python/dtoa.c#L1434\u003e`_\nbut instead of scaling linearly with length of the input string it seems\nto have roughly constant performance. By completely bypassing the CPython\nconverter we get significant performance gains with no penalty, so you\nshould always see improved performance with ``fastnumbers`` for floats.\n\nInstallation\n------------\n\nUse ``pip``!\n\n.. code-block::\n\n    $ pip install fastnumbers\n\nHow to Run Tests\n----------------\n\nPlease note that ``fastnumbers`` is NOT set-up to support\n``python setup.py test``.\n\nThe recommended way to run tests is with\n`tox \u003chttps://tox.readthedocs.io/en/latest/\u003e`_.\nSuppose you want to run tests for Python 3.8 - you can run tests by simply\nexecuting the following:\n\n.. code-block:: sh\n\n    $ tox run -e py38\n\n``tox`` will create virtual a virtual environment for your tests and install\nall the needed testing requirements for you.\n\nIf you want to run testing on all supported Python versions you can simply execute\n\n.. code-block:: sh\n\n    $ tox run\n\nYou can change the how much \"random\" input your tests will try with\n\n.. code-block:: sh\n\n    # Run fewer tests with \"random\" input - much faster\n    $ tox run -- --hypothesis-profile fast\n\n    # Run more tests with \"random\" input - takes much longer but is more thorough\n    $ tox run -- --hypothesis-profile thorough\n\nIf you want to run the performce analysis yourself, you can execute\n\n.. code-block:: sh\n\n    # This assumes Python 3.9 - adjust for the version you want to profile\n    $ tox run -e py39-prof\n\nIf you do not wish to use ``tox``, you can install the testing dependencies with the\n``dev-requirements.txt`` file and then run the tests manually using\n`pytest \u003chttps://docs.pytest.org/en/latest/\u003e`_.\n\n.. code-block:: sh\n\n    $ pip install -r dev/requirements.txt\n    $ pytest\n\nAuthor\n------\n\nSeth M. Morton\n\nHistory\n-------\n\nPlease visit the changelog `on GitHub \u003chttps://github.com/SethMMorton/fastnumbers/blob/main/CHANGELOG.md\u003e`_.\n","funding_links":[],"categories":["C++"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSethMMorton%2Ffastnumbers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSethMMorton%2Ffastnumbers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSethMMorton%2Ffastnumbers/lists"}