bin-dec-conversions 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bin_dec_conversions-1.0.0/LICENSE +21 -0
- bin_dec_conversions-1.0.0/PKG-INFO +137 -0
- bin_dec_conversions-1.0.0/README.md +119 -0
- bin_dec_conversions-1.0.0/pyproject.toml +38 -0
- bin_dec_conversions-1.0.0/setup.cfg +4 -0
- bin_dec_conversions-1.0.0/src/bin_dec_conversions/__init__.py +10 -0
- bin_dec_conversions-1.0.0/src/bin_dec_conversions/cli.py +92 -0
- bin_dec_conversions-1.0.0/src/bin_dec_conversions/core.py +34 -0
- bin_dec_conversions-1.0.0/src/bin_dec_conversions.egg-info/PKG-INFO +137 -0
- bin_dec_conversions-1.0.0/src/bin_dec_conversions.egg-info/SOURCES.txt +14 -0
- bin_dec_conversions-1.0.0/src/bin_dec_conversions.egg-info/dependency_links.txt +1 -0
- bin_dec_conversions-1.0.0/src/bin_dec_conversions.egg-info/entry_points.txt +2 -0
- bin_dec_conversions-1.0.0/src/bin_dec_conversions.egg-info/requires.txt +5 -0
- bin_dec_conversions-1.0.0/src/bin_dec_conversions.egg-info/top_level.txt +1 -0
- bin_dec_conversions-1.0.0/tests/test_conversions.py +40 -0
- bin_dec_conversions-1.0.0/tests/test_invalid.py +45 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Marco S. Tornabene
|
|
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.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bin-dec-conversions
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python package that performs conversions with binary and decimal numbers
|
|
5
|
+
Author: Marco S. Tornabene
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/JustM4rk123/bin-dec-conversions
|
|
8
|
+
Project-URL: Issues, https://github.com/JustM4rk123/bin-dec-conversions/issues
|
|
9
|
+
Keywords: binary,decimal,conversions
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: questionary
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: ruff; extra == "dev"
|
|
16
|
+
Requires-Dist: pytest; extra == "dev"
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# bin-dec-conversions
|
|
20
|
+
|
|
21
|
+
Python package that performs conversions between decimal and binary numbers. It can be used as a library, from the command line, or through an interactive prompt.
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- Convert binary strings to decimal integers and the other way around
|
|
26
|
+
- Optional zero-padding to a minimum width when producing binary output
|
|
27
|
+
- Clear, descriptive error messages for invalid input
|
|
28
|
+
- Command-line interface with flags, plus an interactive menu when run without arguments
|
|
29
|
+
- Fully tested with `pytest`, including a round-trip check for every value from 0 to 255
|
|
30
|
+
|
|
31
|
+
## Requirements
|
|
32
|
+
|
|
33
|
+
- Python 3.10 or newer
|
|
34
|
+
- [`questionary`](https://github.com/tmbo/questionary) (installed automatically, used for the interactive menu)
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install bin-dec-conversions
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
### As a library
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from bin_dec_conversions import binary_to_decimal, decimal_to_binary
|
|
48
|
+
|
|
49
|
+
binary_to_decimal("1010") # 10
|
|
50
|
+
decimal_to_binary(10) # "1010"
|
|
51
|
+
decimal_to_binary(10, 8) # "00001010" (zero-padded to 8 digits)
|
|
52
|
+
decimal_to_binary(5, 2) # "101" (width is a minimum, never truncates)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
| Function | Description |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| `binary_to_decimal(binary: str) -> int` | Converts a string of `0`s and `1`s to an integer. |
|
|
58
|
+
| `decimal_to_binary(decimal: int, width: int = 0) -> str` | Converts a non-negative integer to a binary string, left-padded with zeros to at least `width` digits. |
|
|
59
|
+
|
|
60
|
+
Both functions raise `ValueError` on invalid input:
|
|
61
|
+
|
|
62
|
+
- `binary_to_decimal` rejects empty strings and any character other than `0` and `1` (including spaces, signs, prefixes like `0b`, underscores and decimal points). The message lists every offending character.
|
|
63
|
+
- `decimal_to_binary` rejects negative numbers and negative widths.
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
>>> binary_to_decimal("1a2")
|
|
67
|
+
ValueError: '1a2' is not a valid binary number: invalid character(s) '2', 'a'. Only 0 and 1 are allowed
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### From the command line
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Binary to decimal
|
|
74
|
+
bin-dec-conversions -d 1010
|
|
75
|
+
# The decimal equivalent of 1010 is: 10
|
|
76
|
+
|
|
77
|
+
# Decimal to binary
|
|
78
|
+
bin-dec-conversions -b 10
|
|
79
|
+
# The binary equivalent of 10 is 1010
|
|
80
|
+
|
|
81
|
+
# Decimal to binary, zero-padded to 8 digits
|
|
82
|
+
bin-dec-conversions -b 10 -w 8
|
|
83
|
+
# The binary equivalent of 10 is 00001010
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
| Option | Description |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| `-d BINARY`, `--to-decimal BINARY` | Convert a binary number to decimal. |
|
|
89
|
+
| `-b DECIMAL`, `--to-binary DECIMAL` | Convert a decimal number to binary. |
|
|
90
|
+
| `-w WIDTH`, `--width WIDTH` | Minimum number of binary digits, zero-padded. Only valid together with `--to-binary`. |
|
|
91
|
+
|
|
92
|
+
`--to-decimal` and `--to-binary` are mutually exclusive.
|
|
93
|
+
|
|
94
|
+
### Interactive mode
|
|
95
|
+
|
|
96
|
+
Run the command with no arguments to open an interactive menu:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
bin-dec-conversions
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
You can choose *Binary to decimal*, *Decimal to binary* (with an optional width), or *Exit*. Invalid input is reported and you are prompted again.
|
|
103
|
+
|
|
104
|
+
## Development
|
|
105
|
+
|
|
106
|
+
Clone the repository and install the package in editable mode with the development dependencies:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
git clone https://github.com/JustM4rk123/bin-dec-conversions.git
|
|
110
|
+
cd bin-dec-conversions
|
|
111
|
+
pip install -e ".[dev]"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Run the tests and the linter:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pytest
|
|
118
|
+
ruff check .
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Project structure
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
src/bin_dec_conversions/
|
|
125
|
+
├── __init__.py # public API and __version__
|
|
126
|
+
├── core.py # conversion functions
|
|
127
|
+
└── cli.py # command-line and interactive interface
|
|
128
|
+
tests/
|
|
129
|
+
├── test_conversions.py
|
|
130
|
+
└── test_invalid.py
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
Released under the [MIT License](LICENSE).
|
|
136
|
+
|
|
137
|
+
Author: Marco S. Tornabene
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# bin-dec-conversions
|
|
2
|
+
|
|
3
|
+
Python package that performs conversions between decimal and binary numbers. It can be used as a library, from the command line, or through an interactive prompt.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Convert binary strings to decimal integers and the other way around
|
|
8
|
+
- Optional zero-padding to a minimum width when producing binary output
|
|
9
|
+
- Clear, descriptive error messages for invalid input
|
|
10
|
+
- Command-line interface with flags, plus an interactive menu when run without arguments
|
|
11
|
+
- Fully tested with `pytest`, including a round-trip check for every value from 0 to 255
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- Python 3.10 or newer
|
|
16
|
+
- [`questionary`](https://github.com/tmbo/questionary) (installed automatically, used for the interactive menu)
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install bin-dec-conversions
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
### As a library
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from bin_dec_conversions import binary_to_decimal, decimal_to_binary
|
|
30
|
+
|
|
31
|
+
binary_to_decimal("1010") # 10
|
|
32
|
+
decimal_to_binary(10) # "1010"
|
|
33
|
+
decimal_to_binary(10, 8) # "00001010" (zero-padded to 8 digits)
|
|
34
|
+
decimal_to_binary(5, 2) # "101" (width is a minimum, never truncates)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
| Function | Description |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| `binary_to_decimal(binary: str) -> int` | Converts a string of `0`s and `1`s to an integer. |
|
|
40
|
+
| `decimal_to_binary(decimal: int, width: int = 0) -> str` | Converts a non-negative integer to a binary string, left-padded with zeros to at least `width` digits. |
|
|
41
|
+
|
|
42
|
+
Both functions raise `ValueError` on invalid input:
|
|
43
|
+
|
|
44
|
+
- `binary_to_decimal` rejects empty strings and any character other than `0` and `1` (including spaces, signs, prefixes like `0b`, underscores and decimal points). The message lists every offending character.
|
|
45
|
+
- `decimal_to_binary` rejects negative numbers and negative widths.
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
>>> binary_to_decimal("1a2")
|
|
49
|
+
ValueError: '1a2' is not a valid binary number: invalid character(s) '2', 'a'. Only 0 and 1 are allowed
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### From the command line
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Binary to decimal
|
|
56
|
+
bin-dec-conversions -d 1010
|
|
57
|
+
# The decimal equivalent of 1010 is: 10
|
|
58
|
+
|
|
59
|
+
# Decimal to binary
|
|
60
|
+
bin-dec-conversions -b 10
|
|
61
|
+
# The binary equivalent of 10 is 1010
|
|
62
|
+
|
|
63
|
+
# Decimal to binary, zero-padded to 8 digits
|
|
64
|
+
bin-dec-conversions -b 10 -w 8
|
|
65
|
+
# The binary equivalent of 10 is 00001010
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
| Option | Description |
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| `-d BINARY`, `--to-decimal BINARY` | Convert a binary number to decimal. |
|
|
71
|
+
| `-b DECIMAL`, `--to-binary DECIMAL` | Convert a decimal number to binary. |
|
|
72
|
+
| `-w WIDTH`, `--width WIDTH` | Minimum number of binary digits, zero-padded. Only valid together with `--to-binary`. |
|
|
73
|
+
|
|
74
|
+
`--to-decimal` and `--to-binary` are mutually exclusive.
|
|
75
|
+
|
|
76
|
+
### Interactive mode
|
|
77
|
+
|
|
78
|
+
Run the command with no arguments to open an interactive menu:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
bin-dec-conversions
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
You can choose *Binary to decimal*, *Decimal to binary* (with an optional width), or *Exit*. Invalid input is reported and you are prompted again.
|
|
85
|
+
|
|
86
|
+
## Development
|
|
87
|
+
|
|
88
|
+
Clone the repository and install the package in editable mode with the development dependencies:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
git clone https://github.com/JustM4rk123/bin-dec-conversions.git
|
|
92
|
+
cd bin-dec-conversions
|
|
93
|
+
pip install -e ".[dev]"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Run the tests and the linter:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pytest
|
|
100
|
+
ruff check .
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Project structure
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
src/bin_dec_conversions/
|
|
107
|
+
├── __init__.py # public API and __version__
|
|
108
|
+
├── core.py # conversion functions
|
|
109
|
+
└── cli.py # command-line and interactive interface
|
|
110
|
+
tests/
|
|
111
|
+
├── test_conversions.py
|
|
112
|
+
└── test_invalid.py
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## License
|
|
116
|
+
|
|
117
|
+
Released under the [MIT License](LICENSE).
|
|
118
|
+
|
|
119
|
+
Author: Marco S. Tornabene
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools >= 77.0.3"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
[project]
|
|
7
|
+
name = "bin-dec-conversions"
|
|
8
|
+
description = "Python package that performs conversions with binary and decimal numbers"
|
|
9
|
+
version = "1.0.0"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
license = "MIT"
|
|
13
|
+
license-files = ["LICENSE"]
|
|
14
|
+
keywords = ["binary", "decimal", "conversions"]
|
|
15
|
+
authors = [
|
|
16
|
+
{name = "Marco S. Tornabene"}
|
|
17
|
+
]
|
|
18
|
+
dependencies = ["questionary"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
[project.optional-dependencies]
|
|
22
|
+
dev = [
|
|
23
|
+
"ruff",
|
|
24
|
+
"pytest",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://github.com/JustM4rk123/bin-dec-conversions"
|
|
29
|
+
Issues = "https://github.com/JustM4rk123/bin-dec-conversions/issues"
|
|
30
|
+
|
|
31
|
+
[tool.setuptools.packages.find]
|
|
32
|
+
where = ["src"]
|
|
33
|
+
|
|
34
|
+
[tool.pytest.ini_options]
|
|
35
|
+
testpaths = ["tests"]
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
bin-dec-conversions = "bin_dec_conversions.cli:main"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
2
|
+
|
|
3
|
+
from .core import binary_to_decimal, decimal_to_binary
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = version("bin-dec-conversions")
|
|
7
|
+
except PackageNotFoundError: # running from source without installing
|
|
8
|
+
__version__ = "unknown"
|
|
9
|
+
|
|
10
|
+
__all__ = ["__version__", "binary_to_decimal", "decimal_to_binary"]
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import questionary
|
|
5
|
+
|
|
6
|
+
from .core import binary_to_decimal, decimal_to_binary
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main():
|
|
10
|
+
parser = argparse.ArgumentParser(prog="bin-dec-conversions")
|
|
11
|
+
group = parser.add_mutually_exclusive_group()
|
|
12
|
+
group.add_argument(
|
|
13
|
+
"-d",
|
|
14
|
+
"--to-decimal",
|
|
15
|
+
metavar="BINARY",
|
|
16
|
+
type=str,
|
|
17
|
+
help="Convert a binary number to decimal",
|
|
18
|
+
)
|
|
19
|
+
group.add_argument(
|
|
20
|
+
"-b",
|
|
21
|
+
"--to-binary",
|
|
22
|
+
metavar="DECIMAL",
|
|
23
|
+
type=int,
|
|
24
|
+
help="Convert a decimal number to binary",
|
|
25
|
+
)
|
|
26
|
+
parser.add_argument(
|
|
27
|
+
"-w",
|
|
28
|
+
"--width",
|
|
29
|
+
metavar="WIDTH",
|
|
30
|
+
type=int,
|
|
31
|
+
help="Minimum number of binary digits, zero-padded (only with --to-binary)",
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
args = parser.parse_args()
|
|
35
|
+
|
|
36
|
+
if args.width is not None and args.to_binary is None:
|
|
37
|
+
parser.error("Width goes only with --to-binary")
|
|
38
|
+
elif args.to_decimal is not None:
|
|
39
|
+
try:
|
|
40
|
+
result = binary_to_decimal(args.to_decimal)
|
|
41
|
+
except ValueError as e:
|
|
42
|
+
parser.error(str(e))
|
|
43
|
+
print(f"The decimal equivalent of {args.to_decimal} is: {result}")
|
|
44
|
+
elif args.to_binary is not None:
|
|
45
|
+
try:
|
|
46
|
+
if args.width is not None:
|
|
47
|
+
result = decimal_to_binary(args.to_binary, args.width)
|
|
48
|
+
else:
|
|
49
|
+
result = decimal_to_binary(args.to_binary)
|
|
50
|
+
except ValueError as e:
|
|
51
|
+
parser.error(str(e))
|
|
52
|
+
print(f"The binary equivalent of {args.to_binary} is {result}")
|
|
53
|
+
else:
|
|
54
|
+
conversion = questionary.select(
|
|
55
|
+
"Which conversion do you want to perform?",
|
|
56
|
+
choices=["Binary to decimal", "Decimal to binary", "Exit"],
|
|
57
|
+
).ask()
|
|
58
|
+
|
|
59
|
+
match conversion:
|
|
60
|
+
case "Binary to decimal":
|
|
61
|
+
while True:
|
|
62
|
+
try:
|
|
63
|
+
binary = input("Insert a binary number: ").strip()
|
|
64
|
+
print(
|
|
65
|
+
f"The decimal equivalent of {binary} is {binary_to_decimal(binary)}"
|
|
66
|
+
)
|
|
67
|
+
except ValueError as e:
|
|
68
|
+
print(f"Invalid input: {e}")
|
|
69
|
+
else:
|
|
70
|
+
break
|
|
71
|
+
case "Decimal to binary":
|
|
72
|
+
while True:
|
|
73
|
+
try:
|
|
74
|
+
decimal = int(input("Insert a decimal number: ").strip())
|
|
75
|
+
width_input = input(
|
|
76
|
+
"Width in bits (leave empty for none): "
|
|
77
|
+
).strip()
|
|
78
|
+
if width_input:
|
|
79
|
+
result = decimal_to_binary(decimal, int(width_input))
|
|
80
|
+
else:
|
|
81
|
+
result = decimal_to_binary(decimal)
|
|
82
|
+
print(f"The binary equivalent of {decimal} is {result}")
|
|
83
|
+
except ValueError as e:
|
|
84
|
+
print(f"Invalid input: {e}")
|
|
85
|
+
else:
|
|
86
|
+
break
|
|
87
|
+
case "Exit":
|
|
88
|
+
sys.exit("Program terminated")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
main()
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
def binary_to_decimal(binary: str) -> int:
|
|
2
|
+
if not binary:
|
|
3
|
+
raise ValueError("The input is empty. Enter a binary number made of 0s and 1s")
|
|
4
|
+
|
|
5
|
+
invalid = sorted(set(binary) - {"0", "1"})
|
|
6
|
+
if invalid:
|
|
7
|
+
chars = ", ".join(repr(c) for c in invalid)
|
|
8
|
+
raise ValueError(
|
|
9
|
+
f"'{binary}' is not a valid binary number: "
|
|
10
|
+
f"invalid character(s) {chars}. Only 0 and 1 are allowed"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
decimal = 0
|
|
14
|
+
for i, bit in enumerate(reversed(binary)):
|
|
15
|
+
if bit == "1":
|
|
16
|
+
decimal += 2**i
|
|
17
|
+
return decimal
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def decimal_to_binary(decimal: int, width: int = 0) -> str:
|
|
21
|
+
if decimal < 0:
|
|
22
|
+
raise ValueError(
|
|
23
|
+
f"{decimal} is negative. Only non-negative integers are supported"
|
|
24
|
+
)
|
|
25
|
+
if width < 0:
|
|
26
|
+
raise ValueError(f"Width cannot be negative (got {width})")
|
|
27
|
+
if decimal == 0:
|
|
28
|
+
return "0".zfill(width)
|
|
29
|
+
|
|
30
|
+
bits = []
|
|
31
|
+
while decimal > 0:
|
|
32
|
+
bits.append(str(decimal % 2))
|
|
33
|
+
decimal //= 2
|
|
34
|
+
return "".join(reversed(bits)).zfill(width)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bin-dec-conversions
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python package that performs conversions with binary and decimal numbers
|
|
5
|
+
Author: Marco S. Tornabene
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/JustM4rk123/bin-dec-conversions
|
|
8
|
+
Project-URL: Issues, https://github.com/JustM4rk123/bin-dec-conversions/issues
|
|
9
|
+
Keywords: binary,decimal,conversions
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: questionary
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: ruff; extra == "dev"
|
|
16
|
+
Requires-Dist: pytest; extra == "dev"
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# bin-dec-conversions
|
|
20
|
+
|
|
21
|
+
Python package that performs conversions between decimal and binary numbers. It can be used as a library, from the command line, or through an interactive prompt.
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- Convert binary strings to decimal integers and the other way around
|
|
26
|
+
- Optional zero-padding to a minimum width when producing binary output
|
|
27
|
+
- Clear, descriptive error messages for invalid input
|
|
28
|
+
- Command-line interface with flags, plus an interactive menu when run without arguments
|
|
29
|
+
- Fully tested with `pytest`, including a round-trip check for every value from 0 to 255
|
|
30
|
+
|
|
31
|
+
## Requirements
|
|
32
|
+
|
|
33
|
+
- Python 3.10 or newer
|
|
34
|
+
- [`questionary`](https://github.com/tmbo/questionary) (installed automatically, used for the interactive menu)
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install bin-dec-conversions
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
### As a library
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from bin_dec_conversions import binary_to_decimal, decimal_to_binary
|
|
48
|
+
|
|
49
|
+
binary_to_decimal("1010") # 10
|
|
50
|
+
decimal_to_binary(10) # "1010"
|
|
51
|
+
decimal_to_binary(10, 8) # "00001010" (zero-padded to 8 digits)
|
|
52
|
+
decimal_to_binary(5, 2) # "101" (width is a minimum, never truncates)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
| Function | Description |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| `binary_to_decimal(binary: str) -> int` | Converts a string of `0`s and `1`s to an integer. |
|
|
58
|
+
| `decimal_to_binary(decimal: int, width: int = 0) -> str` | Converts a non-negative integer to a binary string, left-padded with zeros to at least `width` digits. |
|
|
59
|
+
|
|
60
|
+
Both functions raise `ValueError` on invalid input:
|
|
61
|
+
|
|
62
|
+
- `binary_to_decimal` rejects empty strings and any character other than `0` and `1` (including spaces, signs, prefixes like `0b`, underscores and decimal points). The message lists every offending character.
|
|
63
|
+
- `decimal_to_binary` rejects negative numbers and negative widths.
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
>>> binary_to_decimal("1a2")
|
|
67
|
+
ValueError: '1a2' is not a valid binary number: invalid character(s) '2', 'a'. Only 0 and 1 are allowed
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### From the command line
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Binary to decimal
|
|
74
|
+
bin-dec-conversions -d 1010
|
|
75
|
+
# The decimal equivalent of 1010 is: 10
|
|
76
|
+
|
|
77
|
+
# Decimal to binary
|
|
78
|
+
bin-dec-conversions -b 10
|
|
79
|
+
# The binary equivalent of 10 is 1010
|
|
80
|
+
|
|
81
|
+
# Decimal to binary, zero-padded to 8 digits
|
|
82
|
+
bin-dec-conversions -b 10 -w 8
|
|
83
|
+
# The binary equivalent of 10 is 00001010
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
| Option | Description |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| `-d BINARY`, `--to-decimal BINARY` | Convert a binary number to decimal. |
|
|
89
|
+
| `-b DECIMAL`, `--to-binary DECIMAL` | Convert a decimal number to binary. |
|
|
90
|
+
| `-w WIDTH`, `--width WIDTH` | Minimum number of binary digits, zero-padded. Only valid together with `--to-binary`. |
|
|
91
|
+
|
|
92
|
+
`--to-decimal` and `--to-binary` are mutually exclusive.
|
|
93
|
+
|
|
94
|
+
### Interactive mode
|
|
95
|
+
|
|
96
|
+
Run the command with no arguments to open an interactive menu:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
bin-dec-conversions
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
You can choose *Binary to decimal*, *Decimal to binary* (with an optional width), or *Exit*. Invalid input is reported and you are prompted again.
|
|
103
|
+
|
|
104
|
+
## Development
|
|
105
|
+
|
|
106
|
+
Clone the repository and install the package in editable mode with the development dependencies:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
git clone https://github.com/JustM4rk123/bin-dec-conversions.git
|
|
110
|
+
cd bin-dec-conversions
|
|
111
|
+
pip install -e ".[dev]"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Run the tests and the linter:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pytest
|
|
118
|
+
ruff check .
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Project structure
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
src/bin_dec_conversions/
|
|
125
|
+
├── __init__.py # public API and __version__
|
|
126
|
+
├── core.py # conversion functions
|
|
127
|
+
└── cli.py # command-line and interactive interface
|
|
128
|
+
tests/
|
|
129
|
+
├── test_conversions.py
|
|
130
|
+
└── test_invalid.py
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
Released under the [MIT License](LICENSE).
|
|
136
|
+
|
|
137
|
+
Author: Marco S. Tornabene
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/bin_dec_conversions/__init__.py
|
|
5
|
+
src/bin_dec_conversions/cli.py
|
|
6
|
+
src/bin_dec_conversions/core.py
|
|
7
|
+
src/bin_dec_conversions.egg-info/PKG-INFO
|
|
8
|
+
src/bin_dec_conversions.egg-info/SOURCES.txt
|
|
9
|
+
src/bin_dec_conversions.egg-info/dependency_links.txt
|
|
10
|
+
src/bin_dec_conversions.egg-info/entry_points.txt
|
|
11
|
+
src/bin_dec_conversions.egg-info/requires.txt
|
|
12
|
+
src/bin_dec_conversions.egg-info/top_level.txt
|
|
13
|
+
tests/test_conversions.py
|
|
14
|
+
tests/test_invalid.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bin_dec_conversions
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from bin_dec_conversions import binary_to_decimal, decimal_to_binary
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.mark.parametrize(
|
|
7
|
+
"binary, expected",
|
|
8
|
+
[
|
|
9
|
+
("0", 0),
|
|
10
|
+
("1010", 10),
|
|
11
|
+
("101", 5),
|
|
12
|
+
("10000000", 128),
|
|
13
|
+
],
|
|
14
|
+
)
|
|
15
|
+
def test_bin2dec(binary, expected):
|
|
16
|
+
assert binary_to_decimal(binary) == expected
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.mark.parametrize(
|
|
20
|
+
"decimal, expected",
|
|
21
|
+
[
|
|
22
|
+
(0, "0"),
|
|
23
|
+
(10, "1010"),
|
|
24
|
+
(5, "101"),
|
|
25
|
+
(128, "10000000"),
|
|
26
|
+
],
|
|
27
|
+
)
|
|
28
|
+
def test_dec2bin(decimal, expected):
|
|
29
|
+
assert decimal_to_binary(decimal) == expected
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_dec2bin_padding():
|
|
33
|
+
assert decimal_to_binary(10, 8) == "00001010"
|
|
34
|
+
assert decimal_to_binary(0, 8) == "00000000"
|
|
35
|
+
assert decimal_to_binary(5, 2) == "101"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.mark.parametrize("n", range(256))
|
|
39
|
+
def test_round_trip(n):
|
|
40
|
+
assert binary_to_decimal(decimal_to_binary(n)) == n
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from bin_dec_conversions import binary_to_decimal, decimal_to_binary
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.mark.parametrize(
|
|
9
|
+
"invalid, expected_in_message",
|
|
10
|
+
[
|
|
11
|
+
("", "empty"),
|
|
12
|
+
("2", "character(s) '2'"),
|
|
13
|
+
("10_1", "'_'"),
|
|
14
|
+
("-101", "'-'"),
|
|
15
|
+
("0b101", "'b'"),
|
|
16
|
+
(" 101", "' '"),
|
|
17
|
+
("1.0", "'.'"),
|
|
18
|
+
],
|
|
19
|
+
)
|
|
20
|
+
def test_bin2dec_error_messages(invalid, expected_in_message):
|
|
21
|
+
with pytest.raises(ValueError, match=re.escape(expected_in_message)):
|
|
22
|
+
binary_to_decimal(invalid)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_bin2dec_message_echoes_input():
|
|
26
|
+
with pytest.raises(ValueError, match=re.escape("'10_1'")):
|
|
27
|
+
binary_to_decimal("10_1")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_bin2dec_message_lists_every_invalid_char():
|
|
31
|
+
with pytest.raises(ValueError) as exc:
|
|
32
|
+
binary_to_decimal("1a2b")
|
|
33
|
+
assert "'a'" in str(exc.value)
|
|
34
|
+
assert "'2'" in str(exc.value)
|
|
35
|
+
assert "'b'" in str(exc.value)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_dec2bin_negative_number_message():
|
|
39
|
+
with pytest.raises(ValueError, match="negative"):
|
|
40
|
+
decimal_to_binary(-5)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_dec2bin_negative_width_message():
|
|
44
|
+
with pytest.raises(ValueError, match="Width cannot be negative"):
|
|
45
|
+
decimal_to_binary(5, -1)
|