Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow precision specification. #1010

Closed
wants to merge 5 commits into from
Closed

Allow precision specification. #1010

wants to merge 5 commits into from

Conversation

olunusib
Copy link
Contributor

When bypassing decimal quantization, we should be able to specify precision. Fixes #893.

When bypassing decimal quantization, we should be able to specify precision.
Copy link
Member

@akx akx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to overlap with the previously (#494, #577) soft-deprecated frac_prec override... Would it be enough to set pattern.frac_prec = (precision, precision) for the pattern instead of adding the new parameter here in the bowels of Pattern?

Further, I think an exception should be raised when trying to use the mutually exclusive arguments?

babel/numbers.py Outdated Show resolved Hide resolved
@olunusib
Copy link
Contributor Author

olunusib commented Jun 28, 2023

This seems to overlap with the previously (#494, #577) soft-deprecated frac_prec override... Would it be enough to set pattern.frac_prec = (precision, precision) for the pattern instead of adding the new parameter here in the bowels of Pattern?

Further, I think an exception should be raised when trying to use the mutually exclusive arguments?

@akx,

  • No, that won't be enough. If precision is set outside the NumberPattern class, it will be overwritten by this since decimal_quantization is False.
  • Indeed, raising an exception is ideal though the arguments, in this case, aren't mutually exclusive.

olunusib added 3 commits June 28, 2023 04:29
when user specifies precision without setting decimal_quantization to False, we want to raise an exception
@olunusib olunusib requested a review from akx August 24, 2023 02:15
@gdiscry
Copy link

gdiscry commented Sep 7, 2023

I was looking in a similar issue. In my case, I also wanted to use the implicit precision coming with a str or Decimal value, even if the least significant digits are 0.

I came up with the following function to compute the value of the force_frac override for NumberPattern.apply:

def _get_frac_prec(
    pattern: babel.numbers.NumberPattern,
    value: float | decimal.Decimal | str,
    currency: str | None = None,
    currency_digits: bool = True,
    decimal_quantization: bool = True,
    decimal_normalization: bool = True,
    precision: int | None = None,
) -> tuple[int, int]:
    if precision is not None:
        min_prec = max_prec = precision
    elif currency and currency_digits:
        min_prec = max_prec = babel.numbers.get_currency_precision(currency)
    else:
        min_prec, max_prec = pattern.frac_prec

    if decimal_quantization and (
        pattern.exp_prec is None
        or min_prec != 0
        or max_prec != 0
    ):
        return min_prec, max_prec

    # Duplicates the beginning of NumberPattern.apply
    if not isinstance(value, decimal.Decimal):
        value = decimal.Decimal(str(value))
    value = value.scaleb(pattern.scale)

    num_prec = get_decimal_precision(value, normalized=decimal_normalization)
    return max(num_prec, min_prec), max(num_prec, max_prec)

Which requires to add a new parameter to get_decimal_precision to disable normalization:

def get_decimal_precision(number: decimal.Decimal, normalized: bool = True) -> int:
    assert isinstance(number, decimal.Decimal)
    if normalized:
        number = number.normalize()
    exponent = number.as_tuple().exponent
    # Note: DecimalTuple.exponent can be 'n' (qNaN), 'N' (sNaN), or 'F' (Infinity)
    if not isinstance(exponent, int) or exponent >= 0:
        return 0
    return abs(exponent)

When decimal_quantization is enabled, precision sets the exact number of digits after the decimal point. When disabled, precision sets the minimal number of digits, but there can be more digits (with decimal_normalization removing or keeping the non-significant 0).

@olunusib olunusib closed this by deleting the head repository Nov 11, 2023
@FelixSchwarz
Copy link
Contributor

@olunusib Did you close this on purpose or just resignated? I found this PR useful and it was some functionality that would be really useful to have.

@olunusib
Copy link
Contributor Author

@FelixSchwarz It was inadvertently closed. I'll get it back up very soon.

@clj
Copy link

clj commented Jan 19, 2024

Hey @olunusib, I'm just wondering about getting this back up? Seems like some generally useful functionality and it would help me get rid of the warnings I am getting because I'm currently using force_frac to achieve the same as this PR would allow me to do. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

format_percent doesn't return trailing decimal zeros with precision
5 participants