@@ -15,7 +15,7 @@ def exponent_to_multiplier(exponent: int) -> str | None:
15
15
* 0 --> "" (no multiplier)
16
16
* -6 --> "u" (micro)
17
17
18
- If it is not a multiple of 3, returns None.
18
+ If it is not a multiple of 3, return None.
19
19
"""
20
20
if exponent % 3 != 0 :
21
21
return None
@@ -25,11 +25,13 @@ def exponent_to_multiplier(exponent: int) -> str | None:
25
25
26
26
27
27
def multiplier_to_exponent (multiplier : str ) -> int :
28
- """Turns the Metric multiplier into its exponent.
28
+ """Turn the Metric multiplier into its 10^ exponent.
29
29
30
30
* "k" --> 3 (kilo)
31
31
* " " --> 0 (no multiplier)
32
32
* "u" --> -6 (micro)
33
+
34
+ If it is not a valid Metric multiplier, raises an error.
33
35
"""
34
36
if multiplier in (" " , "" ):
35
37
return 0
@@ -38,8 +40,11 @@ def multiplier_to_exponent(multiplier: str) -> int:
38
40
if multiplier == "K" :
39
41
multiplier = multiplier .lower ()
40
42
# 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
43
48
44
49
45
50
def best_exponent (num : Decimal , six : bool ) -> tuple [str , int ]:
@@ -60,16 +65,17 @@ def best_exponent(num: Decimal, six: bool) -> tuple[str, int]:
60
65
# we're trying to avoid getting exponential notation here
61
66
continue
62
67
if "." in new_digits :
68
+ # rarely are significant figures important in component values
63
69
new_digits = new_digits .rstrip ("0" ).removesuffix ("." )
64
70
possibilities .append ((new_digits , new_exp ))
65
71
# heuristics:
66
72
# * shorter is better
67
- # * prefer no decimal point
68
73
# * prefer no Metric multiplier if possible
74
+ # * prefer no decimal point
69
75
return sorted (
70
76
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 ]
73
79
74
80
75
81
def normalize_metric (num : str , six : bool , unicode : bool ) -> tuple [str , str ]:
@@ -114,11 +120,11 @@ def format_metric_unit(
114
120
suffix = num [match .span ()[1 ]:]
115
121
digits0 , exp0 = normalize_metric (num0 , six , unicode )
116
122
digits1 , exp1 = normalize_metric (num1 , six , unicode )
117
- if exp0 != exp1 :
123
+ if exp0 != exp1 and digits0 != "0" :
118
124
# different multiplier so use multiplier and unit on both
119
125
return (f"{ digits0 } { exp0 } { unit } - "
120
126
f"{ digits1 } { exp1 } { unit } { suffix } " ).rstrip ()
121
- return f"{ digits0 } -{ digits1 } { exp0 } { unit } { suffix } " .rstrip ()
127
+ return f"{ digits0 } -{ digits1 } { exp1 } { unit } { suffix } " .rstrip ()
122
128
match = METRIC_NUMBER .match (num )
123
129
if not match :
124
130
return num
@@ -133,7 +139,8 @@ def test(*args):
133
139
print (repr (format_metric_unit (* args )))
134
140
test ("2.5-3500" , "V" )
135
141
test ("50n" , "F" , True )
136
- test ("50M-1000000000000000000000p " , "Hz" )
142
+ test ("50M-100000000000000000000p " , "Hz" )
137
143
test (".1" , "Ω" )
138
144
test ("2200u" , "F" , True )
145
+ test ("0-100k" , "V" )
139
146
test ("Gain" , "Ω" )
0 commit comments