Skip to content

Conversation

javierelpianista
Copy link
Contributor

Implemented the __format__ method for the _mpf type.

Currently, f, F, g, G, e, and E formats are implemented, following the same specifications as specified for regular floats here.
Only nearest rounding is implemented.

Partially resolves #337.

Copy link
Collaborator

@skirpichev skirpichev left a comment

Choose a reason for hiding this comment

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

Very good start!

Please take look on comments. Also, it seems the code is not fully covered by tests (see CI failure).

Copy link
Collaborator

@skirpichev skirpichev left a comment

Choose a reason for hiding this comment

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

LGTM, with one comment on round_digits(). Please address this.

I took liberty to do some stylistic adjustments. Please take look, lets be sure your are OK with this.

Copy link
Collaborator

@skirpichev skirpichev left a comment

Choose a reason for hiding this comment

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

Ah, you should test also subnormal values for floats. Either in test_mpf_float() or in test_mpf_fmt_cpython().

mpf has no restrictions on exponent range, yet I think that output should here match Python's as well.

@javierelpianista
Copy link
Contributor Author

Ah, you should test also subnormal values for floats. Either in test_mpf_float() or in test_mpf_fmt_cpython().

mpf has no restrictions on exponent range, yet I think that output should here match Python's as well.

If I understand you correctly, you mean mpf initialized from floats? Such as

num = 2e-315
print('{:22.15f}'.format(num))
print('{:22.15f}'.format(mpf(num)))
print('{:22.15g}'.format(num))
print('{:22.15g}'.format(mpf(num)))
print('{:22.15e}'.format(num))
print('{:22.15e}'.format(mpf(num)))

resulting in

     0.000000000000000
     0.000000000000000
 2.00000000190402e-315
 2.00000000190402e-315
2.000000001904024e-315
2.000000001904024e-315

But I would expect

num_str = '2e-315'
print('{:22.15f}'.format(mpf(num_str)))
print('{:22.15g}'.format(mpf(num_str)))
print('{:22.15e}'.format(mpf(num_str)))

to result into

     0.000000000000000
                2e-315
2.000000000000000e-315

because in this case the mpf is correctly initialized.

@skirpichev
Copy link
Collaborator

If I understand you correctly, you mean mpf initialized from floats?

Yes, as in other your compatibility tests. And with subnormal values, like in shown example.

But I would expect [...] because in this case the mpf is correctly initialized.

Nothing incorrect in using mpf(float) for default settings.

* Added this functionality to format_scientific and format_fixed functions
* Added random tests for very small numbers to test_format.py
* Added 10 digits to the calls to to_digits_exp, this fixes wrong formatting
  for some subnormal floats.
* Also removed code for no_neg_0 checking in format_scientific, since it
  was never called.
@skirpichev
Copy link
Collaborator

Formatting support must be documented, probably here: https://mpmath.readthedocs.io/en/latest/general.html#conversion-and-printing

But maybe we can do this later in a separate pr.

Copy link
Collaborator

@skirpichev skirpichev left a comment

Choose a reason for hiding this comment

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

LGTM with few comments

# String formatting #
#----------------------------------------------------------------------------#

blog2_10 = 3.3219280948873626
Copy link
Collaborator

Choose a reason for hiding this comment

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

This constant should be moved up (near math_float_inf, I think) and reused in a couple of places:

$ git grep 3.321928 mpmath/libmp/libmpf.py
mpmath/libmp/libmpf.py:    return max(1, int(round(int(n)/3.3219280948873626)-1))
mpmath/libmp/libmpf.py:    return max(1, int(round((int(n)+1)*3.3219280948873626)))
mpmath/libmp/libmpf.py:        prec = int(len(x.as_tuple()[1])*3.3219280948873626)
mpmath/libmp/libmpf.py:        blog2 = 3.3219280948873626

Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
@skirpichev skirpichev merged commit cead3b2 into mpmath:master Jul 24, 2024
@skirpichev
Copy link
Collaborator

@javierelpianista, thank you!

@skirpichev
Copy link
Collaborator

skirpichev commented Jul 25, 2024

@javierelpianista, are you planing to work on mpc.__format__?

@javierelpianista
Copy link
Contributor Author

@javierelpianista, are you planing to work on mpc.__format__?

I could give it a try in the future, but not right now.

@skirpichev skirpichev added this to the 1.4 milestone May 9, 2025
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.

Add mpf.__format__() dunder methods
2 participants