diff --git a/src/humanize/number.py b/src/humanize/number.py index f4dcb05..0f907ce 100644 --- a/src/humanize/number.py +++ b/src/humanize/number.py @@ -538,14 +538,21 @@ def metric(value: float, unit: str = "", precision: int = 3) -> str: if exponent >= 33 or exponent < -30: return scientific(value, precision - 1) + unit - value /= 10 ** (exponent // 3 * 3) + old_bucket = exponent // 3 * 3 + value /= 10**old_bucket + digits = int(max(0, precision - exponent % 3 - 1)) + if exponent < 30 and round(abs(value), digits) >= 1000: + exponent += 3 - exponent % 3 + new_bucket = exponent // 3 * 3 + value /= 10 ** (new_bucket - old_bucket) + digits = int(max(0, precision - exponent % 3 - 1)) if exponent >= 3: ordinal_ = "kMGTPEZYRQ"[exponent // 3 - 1] elif exponent < 0: ordinal_ = "mμnpfazyrq"[(-exponent - 1) // 3] else: ordinal_ = "" - value_ = format(value, f".{int(max(0, precision - exponent % 3 - 1))}f") + value_ = format(value, f".{digits}f") if not (unit or ordinal_) or unit in ("°", "′", "″"): space = "" else: diff --git a/tests/test_number.py b/tests/test_number.py index cb74fcf..cd7c73c 100644 --- a/tests/test_number.py +++ b/tests/test_number.py @@ -254,6 +254,10 @@ def test_clamp(test_args: list[typing.Any], expected: str) -> None: ([1234.56], "1.23 k"), ([12345, "", 6], "12.3450 k"), ([200_000], "200 k"), + ([999.9, "V"], "1.00 kV"), + ([999.99, "V"], "1.00 kV"), + ([999_999, "V"], "1.00 MV"), + ([0.0009999, "V"], "1.00 mV"), ([1e25, "m"], "10.0 Ym"), ([1e26, "m"], "100 Ym"), ([1e27, "A"], "1.00 RA"),