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

math.modf() change integer returned part as integer instead of float #82994

Closed
aikimark1955 mannequin opened this issue Nov 15, 2019 · 8 comments
Closed

math.modf() change integer returned part as integer instead of float #82994

aikimark1955 mannequin opened this issue Nov 15, 2019 · 8 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@aikimark1955
Copy link
Mannequin

aikimark1955 mannequin commented Nov 15, 2019

BPO 38813
Nosy @tim-one, @rhettinger, @mdickinson, @serhiy-storchaka

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2019-11-16.15:48:51.198>
created_at = <Date 2019-11-15.15:02:00.973>
labels = ['type-bug', 'library']
title = 'math.modf() change integer returned part as integer instead of float'
updated_at = <Date 2019-11-16.15:48:51.194>
user = 'https://bugs.python.org/aikimark1955'

bugs.python.org fields:

activity = <Date 2019-11-16.15:48:51.194>
actor = 'mark.dickinson'
assignee = 'none'
closed = True
closed_date = <Date 2019-11-16.15:48:51.198>
closer = 'mark.dickinson'
components = ['Library (Lib)']
creation = <Date 2019-11-15.15:02:00.973>
creator = 'aikimark1955'
dependencies = []
files = []
hgrepos = []
issue_num = 38813
keywords = []
message_count = 8.0
messages = ['356680', '356686', '356707', '356725', '356748', '356749', '356751', '356752']
nosy_count = 5.0
nosy_names = ['tim.peters', 'rhettinger', 'mark.dickinson', 'serhiy.storchaka', 'aikimark1955']
pr_nums = []
priority = 'normal'
resolution = 'rejected'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue38813'
versions = []

@aikimark1955
Copy link
Mannequin Author

aikimark1955 mannequin commented Nov 15, 2019

The description for this function reads:
"Return the fractional and integer parts of x. Both results carry the sign of x and are floats."

Since the second returned value is "integer parts", I submit that the value should be integer.

@aikimark1955 aikimark1955 mannequin added stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error labels Nov 15, 2019
@rhettinger
Copy link
Contributor

This is odd. The underlying C library modf() returns an integer for the second part. Likewise the Python math.frexp() function returns an integer for the second part. So, I'm not sure why Python's math.modf() returns a float for the second field.

@tim-one
Copy link
Member

tim-one commented Nov 15, 2019

Raymond, I think you've tricked yourself ;-) The prototype for C's duoble modf is

double modf(double x, double *intptr);

Yes, after the call *intptr is an exact integer, but in the double format.

>>> math.modf(1e300)
(0.0, 1e+300)

I don't think it would be doing anyone a real favor by returning

1000000000000000052504760255204420248704468581108159154915854115511802457988908195786371375080447864043704443832883878176942523235360430575644792184786706982848387200926575803737830233794788090059368953234970799945081119038967640880074652742780142494579258788820056842838115669472196386865459400540160

instead of 1e300 for "the integer part".

frexp() is very different, in that the second part is a (small!) integer exponent - a float would work for that too, but would be surprising.

>>> math.frexp(1e300)
(0.7466108948025751, 997)

A better analogy would be to math.floor(), which does return an int, even for cases like floor(1e300). In Python 2 it did not (it returned an integer but in float format), and I believe it was a mistake to change it to return an int. Building giant ints is not what C does, so is surprising on that count alone, and is far more expensive than returning (as C does) a float.

That is, we didn't improve on C's floor, we introduced a surprising difference that sometimes hurts and rarely helps (if anyone really wanted an int, they could apply int() to the float result).

@rhettinger
Copy link
Contributor

Raymond, I think you've tricked yourself ;-)

Yup.

@mdickinson
Copy link
Member

[Tim]

I don't think it would be doing anyone a real favor by returning [...]

Agreed.

math.floor(), which does return an int, [...] and I believe it was a mistake to change it to return an int.

Also agreed.

@serhiy-storchaka
Copy link
Member

math.floor(), which does return an int, [...] and I believe it was a mistake to change it to return an int.

What about math.trunc() and round()? Should they return int or float?

And what about the result of the floor division of floats? Should it be int or float?

@mdickinson
Copy link
Member

[Serhiy]

What about math.trunc() and round()? Should they return int or float?

math.trunc was deliberately introduced to be an explicitly-value-modifying conversion to int (as opposed to "int" itself, which is used for both lossy and lossless conversions to int); so from that perspective it should return int.

round is less problematic than floor and ceil because it provides a way to preserve the type (by using 0 as the second argument).

Single-argument round frequently turns out to be the right way to convert a float to an int in practice (e.g., in something like nsteps = round((stop - start) / step), in a case where you know in advance that mathematically stop - start is a small integer multiple of step, but floating-point errors might cause the quotient to deviate from that integer by a small amount in either direction), so I've often appreciated the convenience of being able to use round(some_float) instead of int(round(some_float)).

Floor division of floats already returns a float, and I can't see a strong reason to change that. It's not exactly the most useful floating-point operation in the first place, so it's hard to find use-cases that argue for one return type over the other.

But I think all of this is academic: it's another case of "Should we have done this differently in the first place?" versus "Should we change it now?". The answer to the first question *might* be "Yes" for some pieces, but the answer to the second is almost certainly "No".

@mdickinson
Copy link
Member

Thanks for the suggestion. I'm closing this as rejected, for the reasons Tim gave.

@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

4 participants