baseconvert 2.0.2__tar.gz → 2.0.4__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.
- {baseconvert-2.0.2/baseconvert.egg-info → baseconvert-2.0.4}/PKG-INFO +1 -1
- {baseconvert-2.0.2 → baseconvert-2.0.4}/README.md +9 -0
- baseconvert-2.0.4/VERSION.txt +1 -0
- {baseconvert-2.0.2 → baseconvert-2.0.4}/baseconvert/ButtonRow.qml +2 -1
- {baseconvert-2.0.2 → baseconvert-2.0.4}/baseconvert/__init__.py +1 -0
- baseconvert-2.0.4/baseconvert/__main__.py +89 -0
- {baseconvert-2.0.2 → baseconvert-2.0.4}/baseconvert/app.qml +43 -23
- {baseconvert-2.0.2 → baseconvert-2.0.4}/baseconvert/baseconvert.py +59 -34
- {baseconvert-2.0.2 → baseconvert-2.0.4}/baseconvert/gui.py +4 -7
- {baseconvert-2.0.2 → baseconvert-2.0.4/baseconvert.egg-info}/PKG-INFO +1 -1
- baseconvert-2.0.2/VERSION.txt +0 -1
- baseconvert-2.0.2/baseconvert/__main__.py +0 -51
- {baseconvert-2.0.2 → baseconvert-2.0.4}/LICENSE.txt +0 -0
- {baseconvert-2.0.2 → baseconvert-2.0.4}/MANIFEST.in +0 -0
- {baseconvert-2.0.2 → baseconvert-2.0.4}/README.rst +0 -0
- {baseconvert-2.0.2 → baseconvert-2.0.4}/baseconvert.egg-info/SOURCES.txt +0 -0
- {baseconvert-2.0.2 → baseconvert-2.0.4}/baseconvert.egg-info/dependency_links.txt +0 -0
- {baseconvert-2.0.2 → baseconvert-2.0.4}/baseconvert.egg-info/entry_points.txt +0 -0
- {baseconvert-2.0.2 → baseconvert-2.0.4}/baseconvert.egg-info/requires.txt +0 -0
- {baseconvert-2.0.2 → baseconvert-2.0.4}/baseconvert.egg-info/top_level.txt +0 -0
- {baseconvert-2.0.2 → baseconvert-2.0.4}/setup.cfg +0 -0
- {baseconvert-2.0.2 → baseconvert-2.0.4}/setup.py +0 -0
|
@@ -7,6 +7,15 @@ Convert rational numbers between bases.
|
|
|
7
7
|
|
|
8
8
|
[https://github.com/BreadMakesYouFull/baseconvert](https://github.com/BreadMakesYouFull/baseconvert)
|
|
9
9
|
|
|
10
|
+
<a href='https://flathub.org/apps/io.github.breadmakesyoufull.baseconvert'>
|
|
11
|
+
<img width='128' alt='Get it on Flathub' src='https://flathub.org/api/badge?locale=en'/>
|
|
12
|
+
Install for linux via flatpak
|
|
13
|
+
</a>
|
|
14
|
+
|
|
15
|
+
[](https://badge.fury.io/py/baseconvert) [](https://github.com/BreadMakesYouFull/baseconvert/actions/workflows/lint-then-test.yml)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
10
19
|
## Install
|
|
11
20
|
|
|
12
21
|
Requires:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.0.4
|
|
@@ -17,7 +17,8 @@ Item {
|
|
|
17
17
|
property bool enable5: true
|
|
18
18
|
property bool enable6: true
|
|
19
19
|
signal buttonPressed(text: string)
|
|
20
|
-
property bool
|
|
20
|
+
property bool is_windows: Qt.platform.os == "windows" // Just use light mode on windows for simplicity
|
|
21
|
+
property bool darkMode: is_windows ? false : (Application.styleHints.colorScheme === Qt.ColorScheme.Dark)
|
|
21
22
|
property color color1: darkMode ? "#333333" : "#ffffff"
|
|
22
23
|
property color colorText1: darkMode ? "#ffffff" : "#000000"
|
|
23
24
|
property color color2: darkMode ? "#333333" : "#ffffff"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from baseconvert import base
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
import argparse
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main():
|
|
9
|
+
"""
|
|
10
|
+
Main entry point for running baseconvert as a command.
|
|
11
|
+
|
|
12
|
+
Examples:
|
|
13
|
+
|
|
14
|
+
$ python -m baseconvert -n 0.5 -i 10 -o 20 -s True
|
|
15
|
+
0.A
|
|
16
|
+
|
|
17
|
+
$ echo 3.1415926 | python -m baseconvert -i 10 -o 16 -d 3 -s True
|
|
18
|
+
3.243
|
|
19
|
+
"""
|
|
20
|
+
# Parse arguments
|
|
21
|
+
parser = argparse.ArgumentParser(
|
|
22
|
+
description="Convert rational numbers between bases."
|
|
23
|
+
)
|
|
24
|
+
parser.add_argument(
|
|
25
|
+
"-n",
|
|
26
|
+
"--number",
|
|
27
|
+
default=None,
|
|
28
|
+
help="The number to convert as a string, else stdin used.",
|
|
29
|
+
)
|
|
30
|
+
parser.add_argument(
|
|
31
|
+
"-i", "--input-base", default=10, help="The input base (default 10)."
|
|
32
|
+
)
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
"-o", "--output-base", default=10, help="The output base (default 10)."
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"-d",
|
|
38
|
+
"--max_depth",
|
|
39
|
+
default=10,
|
|
40
|
+
type=int,
|
|
41
|
+
help="The maximum fractional digits (default 10).",
|
|
42
|
+
)
|
|
43
|
+
parser.add_argument(
|
|
44
|
+
"-r",
|
|
45
|
+
"--recurring",
|
|
46
|
+
default=True,
|
|
47
|
+
type=bool,
|
|
48
|
+
help="Boolean, if True will attempt to find recurring decimals (default True).",
|
|
49
|
+
)
|
|
50
|
+
parser.add_argument(
|
|
51
|
+
"-s",
|
|
52
|
+
"--string",
|
|
53
|
+
type=bool,
|
|
54
|
+
help="Boolean, if True will output number as String, else as tuple (default False).",
|
|
55
|
+
)
|
|
56
|
+
args = parser.parse_args()
|
|
57
|
+
|
|
58
|
+
args.input_base = float(args.input_base)
|
|
59
|
+
args.output_base = float(args.output_base)
|
|
60
|
+
if args.input_base == int(args.input_base):
|
|
61
|
+
args.input_base = int(args.input_base)
|
|
62
|
+
if args.output_base == int(args.output_base):
|
|
63
|
+
args.output_base = int(args.output_base)
|
|
64
|
+
if args.number:
|
|
65
|
+
return base(
|
|
66
|
+
args.number,
|
|
67
|
+
args.input_base,
|
|
68
|
+
args.output_base,
|
|
69
|
+
string=args.string,
|
|
70
|
+
max_depth=args.max_depth,
|
|
71
|
+
recurring=args.recurring,
|
|
72
|
+
)
|
|
73
|
+
elif not sys.stdin.isatty():
|
|
74
|
+
return base(
|
|
75
|
+
sys.stdin.read().strip(),
|
|
76
|
+
args.input_base,
|
|
77
|
+
args.output_base,
|
|
78
|
+
string=args.string,
|
|
79
|
+
max_depth=args.max_depth,
|
|
80
|
+
recurring=args.recurring,
|
|
81
|
+
)
|
|
82
|
+
else:
|
|
83
|
+
from .gui import main
|
|
84
|
+
|
|
85
|
+
main()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
if __name__ == "__main__":
|
|
89
|
+
print(main())
|
|
@@ -4,16 +4,31 @@ import QtQuick.Layouts
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
ApplicationWindow {
|
|
7
|
+
id: main
|
|
7
8
|
width: 400
|
|
8
9
|
height: 400
|
|
10
|
+
minimumWidth: 300
|
|
11
|
+
minimumHeight: 150
|
|
9
12
|
visible: true
|
|
10
13
|
title: "baseconvert"
|
|
11
14
|
property string result: ""
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
property bool is_windows: Qt.platform.os == "windows" // Just use light mode on windows for simplicity
|
|
16
|
+
property bool darkMode: is_windows ? false : (Application.styleHints.colorScheme === Qt.ColorScheme.Dark)
|
|
17
|
+
font: Qt.font({
|
|
18
|
+
bold: true,
|
|
19
|
+
underline: false,
|
|
20
|
+
pixelSize: ((main.height > 300) ? ((main.height > main.width) ? main.width / 30 : main.height / 30) : main.height / 8) * 1.1, // resize relative to parent
|
|
21
|
+
family: "monospace"
|
|
22
|
+
})
|
|
23
|
+
property var fontLarge: Qt.font({
|
|
24
|
+
bold: true,
|
|
25
|
+
underline: false,
|
|
26
|
+
pixelSize: main.font.pixelSize * 1.5,
|
|
27
|
+
family: "monospace"
|
|
28
|
+
})
|
|
15
29
|
|
|
16
30
|
ColumnLayout {
|
|
31
|
+
id: mainLayout
|
|
17
32
|
anchors.fill: parent
|
|
18
33
|
RowLayout {
|
|
19
34
|
TextField {
|
|
@@ -21,22 +36,19 @@ ApplicationWindow {
|
|
|
21
36
|
Layout.fillWidth: true
|
|
22
37
|
Layout.columnSpan: 1
|
|
23
38
|
placeholderText: qsTr("Input")
|
|
39
|
+
font: main.fontLarge
|
|
24
40
|
onTextChanged: {
|
|
25
41
|
input.text = input.text.toUpperCase().replace(/[^A-Z0-9.]/g, '')
|
|
26
42
|
backend.input_changed(input.text, from.value, to.value);
|
|
27
43
|
}
|
|
28
44
|
width: parent.width
|
|
29
|
-
font.pointSize: 18
|
|
30
45
|
focus: true
|
|
31
46
|
}
|
|
32
47
|
}
|
|
33
48
|
RowLayout {
|
|
34
49
|
Label {
|
|
35
50
|
id: from_text
|
|
36
|
-
text: "
|
|
37
|
-
textFormat: Text.MarkdownText
|
|
38
|
-
Layout.fillWidth: false
|
|
39
|
-
Layout.preferredWidth: parent.width / 3
|
|
51
|
+
text: "from 10"
|
|
40
52
|
horizontalAlignment: Qt.AlignRight
|
|
41
53
|
}
|
|
42
54
|
Slider {
|
|
@@ -49,17 +61,16 @@ ApplicationWindow {
|
|
|
49
61
|
stepSize: 1
|
|
50
62
|
onValueChanged: {
|
|
51
63
|
backend.input_changed(input.text, from.value, to.value);
|
|
52
|
-
from_text.text = "
|
|
64
|
+
from_text.text = "from " + from.value.toString();
|
|
53
65
|
}
|
|
66
|
+
handle.implicitWidth: to_text.height
|
|
67
|
+
handle.implicitHeight: to_text.height
|
|
54
68
|
}
|
|
55
69
|
}
|
|
56
70
|
RowLayout {
|
|
57
71
|
Label {
|
|
58
72
|
id: to_text
|
|
59
|
-
text: "
|
|
60
|
-
textFormat: Text.MarkdownText
|
|
61
|
-
Layout.fillWidth: false
|
|
62
|
-
Layout.preferredWidth: parent.width / 3
|
|
73
|
+
text: " to 36"
|
|
63
74
|
horizontalAlignment: Qt.AlignRight
|
|
64
75
|
}
|
|
65
76
|
Slider {
|
|
@@ -72,23 +83,25 @@ ApplicationWindow {
|
|
|
72
83
|
stepSize: 1
|
|
73
84
|
onValueChanged: {
|
|
74
85
|
backend.input_changed(input.text, from.value, to.value);
|
|
75
|
-
to_text.text = "
|
|
86
|
+
to_text.text = " to " + to.value.toString();
|
|
76
87
|
}
|
|
88
|
+
handle.implicitWidth: to_text.height
|
|
89
|
+
handle.implicitHeight: to_text.height
|
|
77
90
|
}
|
|
78
91
|
}
|
|
79
92
|
ColumnLayout {
|
|
80
|
-
|
|
93
|
+
TextField {
|
|
81
94
|
id: output
|
|
82
95
|
text: backend.result
|
|
83
96
|
Layout.fillWidth: true
|
|
84
97
|
Layout.columnSpan: 1
|
|
98
|
+
font: main.fontLarge
|
|
85
99
|
readOnly: true
|
|
86
100
|
width: parent.width
|
|
87
|
-
font.pointSize: 18
|
|
88
|
-
//wrapMode: Text.WrapAnywhere
|
|
89
101
|
}
|
|
90
102
|
}
|
|
91
103
|
ButtonRow{
|
|
104
|
+
visible: (main.height > 300) ? true : false
|
|
92
105
|
Layout.fillWidth: true
|
|
93
106
|
Layout.fillHeight: true
|
|
94
107
|
text1: "FLIP"
|
|
@@ -97,10 +110,10 @@ ApplicationWindow {
|
|
|
97
110
|
text4: "< DELETE"
|
|
98
111
|
enable5: false
|
|
99
112
|
enable6: false
|
|
100
|
-
color1: darkMode ? "#0D47A1" : "#
|
|
101
|
-
color2: darkMode ? "#C8090B" : "#
|
|
102
|
-
color3: darkMode ? "#C8090B" : "#
|
|
103
|
-
color4: darkMode ? "#C63100" : "#
|
|
113
|
+
color1: darkMode ? "#0D47A1" : "#275fb8"
|
|
114
|
+
color2: darkMode ? "#C8090B" : "#f51618"
|
|
115
|
+
color3: darkMode ? "#C8090B" : "#f51618"
|
|
116
|
+
color4: darkMode ? "#C63100" : "#ff6633"
|
|
104
117
|
onButtonPressed: (text) => {
|
|
105
118
|
if( text == "FLIP"){
|
|
106
119
|
var base_from = from.value;
|
|
@@ -130,6 +143,7 @@ ApplicationWindow {
|
|
|
130
143
|
}
|
|
131
144
|
}
|
|
132
145
|
ButtonRow{
|
|
146
|
+
visible: (main.height > 300) ? true : false
|
|
133
147
|
Layout.fillWidth: true
|
|
134
148
|
Layout.fillHeight: true
|
|
135
149
|
text1: "V"
|
|
@@ -144,12 +158,13 @@ ApplicationWindow {
|
|
|
144
158
|
enable5: (from.value >= 36) ? true : false
|
|
145
159
|
enable6: true
|
|
146
160
|
text6: "."
|
|
147
|
-
color6: darkMode ? "#
|
|
161
|
+
color6: darkMode ? "#006064" : "#109ba1"
|
|
148
162
|
onButtonPressed: (text) => {
|
|
149
163
|
input.text += text
|
|
150
164
|
}
|
|
151
165
|
}
|
|
152
166
|
ButtonRow{
|
|
167
|
+
visible: (main.height > 300) ? true : false
|
|
153
168
|
Layout.fillWidth: true
|
|
154
169
|
Layout.fillHeight: (from.value >= 26) ? true : false
|
|
155
170
|
text1: "P"
|
|
@@ -167,6 +182,7 @@ ApplicationWindow {
|
|
|
167
182
|
onButtonPressed: (text) => {input.text += text}
|
|
168
183
|
}
|
|
169
184
|
ButtonRow{
|
|
185
|
+
visible: (main.height > 300) ? true : false
|
|
170
186
|
Layout.fillWidth: true
|
|
171
187
|
Layout.fillHeight: (from.value >= 20) ? true : false
|
|
172
188
|
text1: "J"
|
|
@@ -184,6 +200,7 @@ ApplicationWindow {
|
|
|
184
200
|
onButtonPressed: (text) => {input.text += text}
|
|
185
201
|
}
|
|
186
202
|
ButtonRow{
|
|
203
|
+
visible: (main.height > 300) ? true : false
|
|
187
204
|
Layout.fillWidth: true
|
|
188
205
|
Layout.fillHeight: (from.value >= 14) ? true : false
|
|
189
206
|
text1: "D"
|
|
@@ -201,6 +218,7 @@ ApplicationWindow {
|
|
|
201
218
|
onButtonPressed: (text) => {input.text += text}
|
|
202
219
|
}
|
|
203
220
|
ButtonRow{
|
|
221
|
+
visible: (main.height > 300) ? true : false
|
|
204
222
|
Layout.fillWidth: true
|
|
205
223
|
Layout.fillHeight: (from.value >= 8) ? true : false
|
|
206
224
|
text1: "7"
|
|
@@ -218,6 +236,7 @@ ApplicationWindow {
|
|
|
218
236
|
onButtonPressed: (text) => {input.text += text}
|
|
219
237
|
}
|
|
220
238
|
ButtonRow{
|
|
239
|
+
visible: (main.height > 300) ? true : false
|
|
221
240
|
Layout.fillWidth: true
|
|
222
241
|
Layout.fillHeight: (from.value >= 2) ? true : false
|
|
223
242
|
text1: "1"
|
|
@@ -235,10 +254,11 @@ ApplicationWindow {
|
|
|
235
254
|
onButtonPressed: (text) => {input.text += text}
|
|
236
255
|
}
|
|
237
256
|
ButtonRow{
|
|
257
|
+
visible: (main.height > 300) ? true : false
|
|
238
258
|
Layout.fillWidth: true
|
|
239
259
|
Layout.fillHeight: true
|
|
240
260
|
text1: "0"
|
|
241
|
-
color1: darkMode ? "#0D47A1" : "#
|
|
261
|
+
color1: darkMode ? "#0D47A1" : "#275fb8"
|
|
242
262
|
onButtonPressed: (text) => {input.text += text}
|
|
243
263
|
enable2: false
|
|
244
264
|
enable3: false
|
|
@@ -157,10 +157,7 @@ Exact result:
|
|
|
157
157
|
import sys
|
|
158
158
|
|
|
159
159
|
|
|
160
|
-
__MATH_GCD =
|
|
161
|
-
sys.version_info.major >= 3
|
|
162
|
-
and sys.version_info.minor >= 5
|
|
163
|
-
)
|
|
160
|
+
__MATH_GCD = sys.version_info.major >= 3 and sys.version_info.minor >= 5
|
|
164
161
|
|
|
165
162
|
if __MATH_GCD:
|
|
166
163
|
from math import gcd
|
|
@@ -217,9 +214,17 @@ class BaseConverter:
|
|
|
217
214
|
>>> b((4,5,6,7))
|
|
218
215
|
(4, 2, 5, 4, 7)
|
|
219
216
|
"""
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
217
|
+
|
|
218
|
+
def __init__(
|
|
219
|
+
self,
|
|
220
|
+
input_base,
|
|
221
|
+
output_base,
|
|
222
|
+
max_depth=10,
|
|
223
|
+
string=False,
|
|
224
|
+
recurring=True,
|
|
225
|
+
padding=0,
|
|
226
|
+
exact=False,
|
|
227
|
+
):
|
|
223
228
|
self.input_base = input_base
|
|
224
229
|
self.output_base = output_base
|
|
225
230
|
self.max_depth = max_depth
|
|
@@ -231,8 +236,15 @@ class BaseConverter:
|
|
|
231
236
|
|
|
232
237
|
def __call__(self, number):
|
|
233
238
|
"""Convert a number."""
|
|
234
|
-
return base(
|
|
235
|
-
|
|
239
|
+
return base(
|
|
240
|
+
number,
|
|
241
|
+
self.input_base,
|
|
242
|
+
self.output_base,
|
|
243
|
+
self.max_depth,
|
|
244
|
+
self.string,
|
|
245
|
+
self.recurring,
|
|
246
|
+
self.padding,
|
|
247
|
+
)
|
|
236
248
|
|
|
237
249
|
|
|
238
250
|
def represent_as_tuple(string):
|
|
@@ -266,8 +278,7 @@ def represent_as_string(iterable):
|
|
|
266
278
|
'868.0F'
|
|
267
279
|
"""
|
|
268
280
|
keep = (".", "[", "]")
|
|
269
|
-
return "".join(tuple(int_to_str_digit(i) if i not in keep
|
|
270
|
-
else i for i in iterable))
|
|
281
|
+
return "".join(tuple(int_to_str_digit(i) if i not in keep else i for i in iterable))
|
|
271
282
|
|
|
272
283
|
|
|
273
284
|
def pad(iterable, n):
|
|
@@ -310,16 +321,21 @@ def pad(iterable, n):
|
|
|
310
321
|
('0', '0', 'A', '0', '.', '0', '1')
|
|
311
322
|
"""
|
|
312
323
|
if isinstance(iterable, str):
|
|
313
|
-
return (n - len(iterable.split(".")[0])) *
|
|
324
|
+
return (n - len(iterable.split(".")[0])) * "0" + iterable
|
|
314
325
|
else:
|
|
315
326
|
return tuple(
|
|
316
327
|
(
|
|
317
|
-
n
|
|
318
|
-
|
|
328
|
+
n
|
|
329
|
+
- len(
|
|
330
|
+
iterable[0 : iterable.index(".")]
|
|
319
331
|
if iterable.count(".")
|
|
320
332
|
else iterable
|
|
321
333
|
)
|
|
322
|
-
)
|
|
334
|
+
)
|
|
335
|
+
* [
|
|
336
|
+
"0",
|
|
337
|
+
]
|
|
338
|
+
+ list(iterable)
|
|
323
339
|
)
|
|
324
340
|
|
|
325
341
|
|
|
@@ -354,7 +370,7 @@ def digit(decimal, digit, input_base=10):
|
|
|
354
370
|
if decimal == 0:
|
|
355
371
|
return 0
|
|
356
372
|
if digit != 0:
|
|
357
|
-
return (decimal // (input_base
|
|
373
|
+
return (decimal // (input_base**digit)) % input_base
|
|
358
374
|
else:
|
|
359
375
|
return decimal % input_base
|
|
360
376
|
|
|
@@ -390,7 +406,7 @@ def digits(number, base=10):
|
|
|
390
406
|
return 0
|
|
391
407
|
digits = 0
|
|
392
408
|
n = 1
|
|
393
|
-
while
|
|
409
|
+
while number >= 1:
|
|
394
410
|
number //= base
|
|
395
411
|
digits += 1
|
|
396
412
|
return digits
|
|
@@ -414,7 +430,7 @@ def integer_fractional_parts(number):
|
|
|
414
430
|
radix_point = number.index(".")
|
|
415
431
|
integer_part = number[:radix_point]
|
|
416
432
|
fractional_part = number[radix_point:]
|
|
417
|
-
return(integer_part, fractional_part)
|
|
433
|
+
return (integer_part, fractional_part)
|
|
418
434
|
|
|
419
435
|
|
|
420
436
|
def from_base_10_int(decimal, output_base=10):
|
|
@@ -462,7 +478,7 @@ def to_base_10_int(n, input_base):
|
|
|
462
478
|
>>> to_base_10_int((8,1), 16)
|
|
463
479
|
129
|
|
464
480
|
"""
|
|
465
|
-
return sum(c * input_base
|
|
481
|
+
return sum(c * input_base**i for i, c in enumerate(n[::-1]))
|
|
466
482
|
|
|
467
483
|
|
|
468
484
|
def integer_base(number, input_base=10, output_base=10):
|
|
@@ -495,8 +511,7 @@ def integer_base(number, input_base=10, output_base=10):
|
|
|
495
511
|
return from_base_10_int(to_base_10_int(number, input_base), output_base)
|
|
496
512
|
|
|
497
513
|
|
|
498
|
-
def fractional_base(fractional_part, input_base=10, output_base=10,
|
|
499
|
-
max_depth=10):
|
|
514
|
+
def fractional_base(fractional_part, input_base=10, output_base=10, max_depth=10):
|
|
500
515
|
"""
|
|
501
516
|
Convert the fractional part of a number from any base to any base.
|
|
502
517
|
|
|
@@ -519,17 +534,17 @@ def fractional_base(fractional_part, input_base=10, output_base=10,
|
|
|
519
534
|
numerator = 0
|
|
520
535
|
for i, value in enumerate(fractional_part, 1):
|
|
521
536
|
numerator += value * input_base ** (fractional_digits - i)
|
|
522
|
-
denominator = input_base
|
|
537
|
+
denominator = input_base**fractional_digits
|
|
523
538
|
i = 1
|
|
524
539
|
digits = []
|
|
525
540
|
visited = []
|
|
526
|
-
while
|
|
527
|
-
numerator *= output_base
|
|
541
|
+
while i < max_depth + 1 or (max_depth == 0 and i < MAX_DEPTH):
|
|
542
|
+
numerator *= output_base**i
|
|
528
543
|
digit = numerator // denominator
|
|
529
544
|
remainder = numerator % denominator
|
|
530
545
|
visited.append((digit, remainder))
|
|
531
546
|
numerator -= digit * denominator
|
|
532
|
-
denominator *= output_base
|
|
547
|
+
denominator *= output_base**i
|
|
533
548
|
digits.append(digit)
|
|
534
549
|
i += 1
|
|
535
550
|
greatest_common_divisor = gcd(numerator, denominator)
|
|
@@ -643,13 +658,13 @@ def find_recurring(number, min_repeat=5):
|
|
|
643
658
|
best_period = 0
|
|
644
659
|
best_repeat = 0
|
|
645
660
|
# Find recurring pattern.
|
|
646
|
-
while
|
|
661
|
+
while period < len(sequence):
|
|
647
662
|
period += 1
|
|
648
663
|
pattern = sequence[:period]
|
|
649
664
|
repeat = 0
|
|
650
665
|
digit = period
|
|
651
666
|
pattern_match = True
|
|
652
|
-
while
|
|
667
|
+
while pattern_match and digit < len(sequence):
|
|
653
668
|
for i, pattern_digit in enumerate(pattern):
|
|
654
669
|
if sequence[digit + i] != pattern_digit:
|
|
655
670
|
pattern_match = False
|
|
@@ -669,7 +684,7 @@ def find_recurring(number, min_repeat=5):
|
|
|
669
684
|
# Use the best pattern found.
|
|
670
685
|
pattern = sequence[:best_period]
|
|
671
686
|
# Remove the pattern from our original number.
|
|
672
|
-
number = integer_part + fractional_part[
|
|
687
|
+
number = integer_part + fractional_part[: -(best + best_period)]
|
|
673
688
|
# Ensure we are at the start of the pattern.
|
|
674
689
|
pattern_temp = pattern
|
|
675
690
|
number_temp = number
|
|
@@ -703,7 +718,7 @@ def expand_recurring(number, repeat=5):
|
|
|
703
718
|
"""
|
|
704
719
|
if "[" in number:
|
|
705
720
|
pattern_index = number.index("[")
|
|
706
|
-
pattern = number[pattern_index + 1
|
|
721
|
+
pattern = number[pattern_index + 1 : -1]
|
|
707
722
|
number = number[:pattern_index]
|
|
708
723
|
number = number + pattern * (repeat + 1)
|
|
709
724
|
return number
|
|
@@ -739,8 +754,16 @@ def check_valid(number, input_base=10):
|
|
|
739
754
|
return True
|
|
740
755
|
|
|
741
756
|
|
|
742
|
-
def base(
|
|
743
|
-
|
|
757
|
+
def base(
|
|
758
|
+
number,
|
|
759
|
+
input_base=10,
|
|
760
|
+
output_base=10,
|
|
761
|
+
max_depth=10,
|
|
762
|
+
string=False,
|
|
763
|
+
recurring=True,
|
|
764
|
+
padding=0,
|
|
765
|
+
exact=False,
|
|
766
|
+
):
|
|
744
767
|
"""
|
|
745
768
|
Converts a number from any base to any another.
|
|
746
769
|
|
|
@@ -781,15 +804,16 @@ def base(number, input_base=10, output_base=10, max_depth=10,
|
|
|
781
804
|
if input_base == 1:
|
|
782
805
|
number = (1,) * number.count(1)
|
|
783
806
|
# Expand any recurring digits.
|
|
784
|
-
number = expand_recurring(number, repeat=MAX_DEPTH*2)
|
|
807
|
+
number = expand_recurring(number, repeat=MAX_DEPTH * 2)
|
|
785
808
|
# Convert a fractional number.
|
|
786
809
|
if "." in number:
|
|
787
810
|
radix_point = number.index(".")
|
|
788
811
|
integer_part = number[:radix_point]
|
|
789
812
|
fractional_part = number[radix_point:]
|
|
790
813
|
integer_part = integer_base(integer_part, input_base, output_base)
|
|
791
|
-
fractional_part = fractional_base(
|
|
792
|
-
|
|
814
|
+
fractional_part = fractional_base(
|
|
815
|
+
fractional_part, input_base, output_base, max_depth
|
|
816
|
+
)
|
|
793
817
|
number = integer_part + fractional_part
|
|
794
818
|
number = truncate(number)
|
|
795
819
|
# Convert an integer number.
|
|
@@ -803,4 +827,5 @@ def base(number, input_base=10, output_base=10, max_depth=10,
|
|
|
803
827
|
|
|
804
828
|
if __name__ == "__main__":
|
|
805
829
|
import doctest
|
|
830
|
+
|
|
806
831
|
doctest.testmod(verbose=False)
|
|
@@ -8,9 +8,10 @@ from PySide6.QtQml import QQmlApplicationEngine
|
|
|
8
8
|
|
|
9
9
|
from .baseconvert import base
|
|
10
10
|
|
|
11
|
+
|
|
11
12
|
class Backend(QObject):
|
|
12
13
|
|
|
13
|
-
updateResult=Signal()
|
|
14
|
+
updateResult = Signal()
|
|
14
15
|
|
|
15
16
|
def __init__(self, parent=None):
|
|
16
17
|
super().__init__(parent)
|
|
@@ -21,9 +22,7 @@ class Backend(QObject):
|
|
|
21
22
|
def input_changed(self, value, base_from, base_to):
|
|
22
23
|
if re.match("^[0-9A-Z]*[.]?[0-9A-Z]*$", value):
|
|
23
24
|
try:
|
|
24
|
-
self._result = base(
|
|
25
|
-
value, base_from, base_to, string=True, exact=True
|
|
26
|
-
)
|
|
25
|
+
self._result = base(value, base_from, base_to, string=True, exact=True)
|
|
27
26
|
except:
|
|
28
27
|
self._result = self._default
|
|
29
28
|
else:
|
|
@@ -40,9 +39,7 @@ def main():
|
|
|
40
39
|
app = QGuiApplication(sys.argv)
|
|
41
40
|
engine = QQmlApplicationEngine()
|
|
42
41
|
engine.rootContext().setContextProperty("backend", backend)
|
|
43
|
-
engine.load(
|
|
44
|
-
pkg_resources.resource_filename(__name__, 'app.qml')
|
|
45
|
-
)
|
|
42
|
+
engine.load(pkg_resources.resource_filename(__name__, "app.qml"))
|
|
46
43
|
if not engine.rootObjects():
|
|
47
44
|
sys.exit(-1)
|
|
48
45
|
exit_code = app.exec()
|
baseconvert-2.0.2/VERSION.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.0.2
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
from baseconvert import base
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import sys
|
|
5
|
-
import argparse
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def main():
|
|
9
|
-
"""
|
|
10
|
-
Main entry point for running baseconvert as a command.
|
|
11
|
-
|
|
12
|
-
Examples:
|
|
13
|
-
|
|
14
|
-
$ python -m baseconvert -n 0.5 -i 10 -o 20 -s True
|
|
15
|
-
0.A
|
|
16
|
-
|
|
17
|
-
$ echo 3.1415926 | python -m baseconvert -i 10 -o 16 -d 3 -s True
|
|
18
|
-
3.243
|
|
19
|
-
"""
|
|
20
|
-
# Parse arguments
|
|
21
|
-
parser = argparse.ArgumentParser(description="Convert rational numbers between bases.")
|
|
22
|
-
parser.add_argument("-n", "--number", default=None,
|
|
23
|
-
help="The number to convert as a string, else stdin used.")
|
|
24
|
-
parser.add_argument("-i", "--input-base", default=10,
|
|
25
|
-
help="The input base (default 10).")
|
|
26
|
-
parser.add_argument("-o", "--output-base", default=10,
|
|
27
|
-
help="The output base (default 10).")
|
|
28
|
-
parser.add_argument("-d", "--max_depth", default=10, type=int,
|
|
29
|
-
help="The maximum fractional digits (default 10).")
|
|
30
|
-
parser.add_argument("-r", "--recurring", default=True, type=bool,
|
|
31
|
-
help="Boolean, if True will attempt to find recurring decimals (default True).")
|
|
32
|
-
parser.add_argument("-s", "--string", type=bool,
|
|
33
|
-
help="Boolean, if True will output number as String, else as tuple (default False).")
|
|
34
|
-
args = parser.parse_args()
|
|
35
|
-
|
|
36
|
-
args.input_base = float(args.input_base)
|
|
37
|
-
args.output_base = float(args.output_base)
|
|
38
|
-
if args.input_base == int(args.input_base):
|
|
39
|
-
args.input_base = int(args.input_base)
|
|
40
|
-
if args.output_base == int(args.output_base):
|
|
41
|
-
args.output_base = int(args.output_base)
|
|
42
|
-
if (args.number):
|
|
43
|
-
return base(args.number, args.input_base, args.output_base, string=args.string, max_depth=args.max_depth, recurring=args.recurring)
|
|
44
|
-
elif not sys.stdin.isatty():
|
|
45
|
-
return base(sys.stdin.read().strip(), args.input_base, args.output_base, string=args.string, max_depth=args.max_depth, recurring=args.recurring)
|
|
46
|
-
else:
|
|
47
|
-
from .gui import main
|
|
48
|
-
main()
|
|
49
|
-
|
|
50
|
-
if __name__ == "__main__":
|
|
51
|
-
print(main())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|