Skip to content

First commit for add_prefix_conversion #5453

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions conversions/add_prefix_conversion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"""
* Author: Manuel Di Lullo (https://github.com/manueldilullo)
* Description: Convert a number to use the correct SI or Binary unit prefix.

Inspired by prefix_conversion.py file in this repository by lance-pyles

URL: https://en.wikipedia.org/wiki/Metric_prefix#List_of_SI_prefixes
URL: https://en.wikipedia.org/wiki/Binary_prefix
"""

from __future__ import annotations

from enum import Enum, unique
from typing import Type, TypeVar

# Create a generic variable that can be 'Enum', or any subclass.
T = TypeVar("T", bound="Enum")


@unique
class BinaryUnit(Enum):
yotta = 80
zetta = 70
exa = 60
peta = 50
tera = 40
giga = 30
mega = 20
kilo = 10


@unique
class SIUnit(Enum):
yotta = 24
zetta = 21
exa = 18
peta = 15
tera = 12
giga = 9
mega = 6
kilo = 3
hecto = 2
deca = 1
deci = -1
centi = -2
milli = -3
micro = -6
nano = -9
pico = -12
femto = -15
atto = -18
zepto = -21
yocto = -24

@classmethod
def get_positive(cls: Type[T]) -> dict:
"""
Returns a dictionary with only the elements of this enum
that has a positive value
>>> from itertools import islice
>>> positive = SIUnit.get_positive()
>>> inc = iter(positive.items())
>>> dict(islice(inc, len(positive) // 2))
{'yotta': 24, 'zetta': 21, 'exa': 18, 'peta': 15, 'tera': 12}
>>> dict(inc)
{'giga': 9, 'mega': 6, 'kilo': 3, 'hecto': 2, 'deca': 1}
"""
return {unit.name: unit.value for unit in cls if unit.value > 0}

@classmethod
def get_negative(cls: Type[T]) -> dict:
"""
Returns a dictionary with only the elements of this enum
that has a negative value
@example
>>> from itertools import islice
>>> negative = SIUnit.get_negative()
>>> inc = iter(negative.items())
>>> dict(islice(inc, len(negative) // 2))
{'deci': -1, 'centi': -2, 'milli': -3, 'micro': -6, 'nano': -9}
>>> dict(inc)
{'pico': -12, 'femto': -15, 'atto': -18, 'zepto': -21, 'yocto': -24}
"""
return {unit.name: unit.value for unit in cls if unit.value < 0}


def add_si_prefix(value: float) -> str:
"""
Function that converts a number to his version with SI prefix
@input value (an integer)
@example:
>>> add_si_prefix(10000)
'10.0 kilo'
"""
prefixes = SIUnit.get_positive() if value > 0 else SIUnit.get_negative()
for name_prefix, value_prefix in prefixes.items():
numerical_part = value / (10 ** value_prefix)
if numerical_part > 1:
return f"{str(numerical_part)} {name_prefix}"
return str(value)


def add_binary_prefix(value: float) -> str:
"""
Function that converts a number to his version with Binary prefix
@input value (an integer)
@example:
>>> add_binary_prefix(65536)
'64.0 kilo'
"""
for prefix in BinaryUnit:
numerical_part = value / (2 ** prefix.value)
if numerical_part > 1:
return f"{str(numerical_part)} {prefix.name}"
return str(value)


if __name__ == "__main__":
import doctest

doctest.testmod()