Skip to content

Commit 0dfcbde

Browse files
special case 0 can take any multiplier because it's 0
1 parent 6d70fb9 commit 0dfcbde

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

schemascii/metric.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def exponent_to_multiplier(exponent: int) -> str | None:
1515
* 0 --> "" (no multiplier)
1616
* -6 --> "u" (micro)
1717
18-
If it is not a multiple of 3, returns None.
18+
If it is not a multiple of 3, return None.
1919
"""
2020
if exponent % 3 != 0:
2121
return None
@@ -25,11 +25,13 @@ def exponent_to_multiplier(exponent: int) -> str | None:
2525

2626

2727
def multiplier_to_exponent(multiplier: str) -> int:
28-
"""Turns the Metric multiplier into its exponent.
28+
"""Turn the Metric multiplier into its 10^exponent.
2929
3030
* "k" --> 3 (kilo)
3131
* " " --> 0 (no multiplier)
3232
* "u" --> -6 (micro)
33+
34+
If it is not a valid Metric multiplier, raises an error.
3335
"""
3436
if multiplier in (" ", ""):
3537
return 0
@@ -38,8 +40,11 @@ def multiplier_to_exponent(multiplier: str) -> int:
3840
if multiplier == "K":
3941
multiplier = multiplier.lower()
4042
# special case (preferred is lowercase)
41-
i = "pnum kMGT".index(multiplier)
42-
return (i - 4) * 3
43+
try:
44+
return 3 * ("pnum kMGT".index(multiplier) - 4)
45+
except IndexError as e:
46+
raise ValueError(
47+
f"unknown metric multiplier: {multiplier!r}") from e
4348

4449

4550
def best_exponent(num: Decimal, six: bool) -> tuple[str, int]:
@@ -60,16 +65,17 @@ def best_exponent(num: Decimal, six: bool) -> tuple[str, int]:
6065
# we're trying to avoid getting exponential notation here
6166
continue
6267
if "." in new_digits:
68+
# rarely are significant figures important in component values
6369
new_digits = new_digits.rstrip("0").removesuffix(".")
6470
possibilities.append((new_digits, new_exp))
6571
# heuristics:
6672
# * shorter is better
67-
# * prefer no decimal point
6873
# * prefer no Metric multiplier if possible
74+
# * prefer no decimal point
6975
return sorted(
7076
possibilities, key=lambda x: ((10 * len(x[0]))
71-
+ (2 * ("." in x[0]))
72-
+ (5 * (x[1] != 0))))[0]
77+
+ (5 * (x[1] != 0))
78+
+ (2 * ("." in x[0]))))[0]
7379

7480

7581
def normalize_metric(num: str, six: bool, unicode: bool) -> tuple[str, str]:
@@ -114,11 +120,11 @@ def format_metric_unit(
114120
suffix = num[match.span()[1]:]
115121
digits0, exp0 = normalize_metric(num0, six, unicode)
116122
digits1, exp1 = normalize_metric(num1, six, unicode)
117-
if exp0 != exp1:
123+
if exp0 != exp1 and digits0 != "0":
118124
# different multiplier so use multiplier and unit on both
119125
return (f"{digits0} {exp0}{unit} - "
120126
f"{digits1} {exp1}{unit} {suffix}").rstrip()
121-
return f"{digits0}-{digits1} {exp0}{unit} {suffix}".rstrip()
127+
return f"{digits0}-{digits1} {exp1}{unit} {suffix}".rstrip()
122128
match = METRIC_NUMBER.match(num)
123129
if not match:
124130
return num
@@ -133,7 +139,8 @@ def test(*args):
133139
print(repr(format_metric_unit(*args)))
134140
test("2.5-3500", "V")
135141
test("50n", "F", True)
136-
test("50M-1000000000000000000000p", "Hz")
142+
test("50M-100000000000000000000p", "Hz")
137143
test(".1", "Ω")
138144
test("2200u", "F", True)
145+
test("0-100k", "V")
139146
test("Gain", "Ω")

0 commit comments

Comments
 (0)