Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
1492456e
Commit
1492456e
authored
Mar 26, 2011
by
Mark Dickinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #11144: Fix corner cases where float-to-int conversion unnecessarily returned a long.
parent
50777650
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
56 additions
and
7 deletions
+56
-7
Lib/test/test_float.py
Lib/test/test_float.py
+42
-0
Misc/NEWS
Misc/NEWS
+4
-0
Objects/floatobject.c
Objects/floatobject.c
+10
-7
No files found.
Lib/test/test_float.py
View file @
1492456e
...
...
@@ -52,6 +52,48 @@ class GeneralFloatCases(unittest.TestCase):
float
(
'.'
+
'1'
*
1000
)
float
(
unicode
(
'.'
+
'1'
*
1000
))
def
check_conversion_to_int
(
self
,
x
):
"""Check that int(x) has the correct value and type, for a float x."""
n
=
int
(
x
)
if
x
>=
0.0
:
# x >= 0 and n = int(x) ==> n <= x < n + 1
self
.
assertLessEqual
(
n
,
x
)
self
.
assertLess
(
x
,
n
+
1
)
else
:
# x < 0 and n = int(x) ==> n >= x > n - 1
self
.
assertGreaterEqual
(
n
,
x
)
self
.
assertGreater
(
x
,
n
-
1
)
# Result should be an int if within range, else a long.
if
-
sys
.
maxint
-
1
<=
n
<=
sys
.
maxint
:
self
.
assertEqual
(
type
(
n
),
int
)
else
:
self
.
assertEqual
(
type
(
n
),
long
)
# Double check.
self
.
assertEqual
(
type
(
int
(
n
)),
type
(
n
))
def
test_conversion_to_int
(
self
):
# Check that floats within the range of an int convert to type
# int, not long. (issue #11144.)
boundary
=
float
(
sys
.
maxint
+
1
)
epsilon
=
2
**-
sys
.
float_info
.
mant_dig
*
boundary
# These 2 floats are either side of the positive int/long boundary on
# both 32-bit and 64-bit systems.
self
.
check_conversion_to_int
(
boundary
-
epsilon
)
self
.
check_conversion_to_int
(
boundary
)
# These floats are either side of the negative long/int boundary on
# 64-bit systems...
self
.
check_conversion_to_int
(
-
boundary
-
2
*
epsilon
)
self
.
check_conversion_to_int
(
-
boundary
)
# ... and these ones are either side of the negative long/int
# boundary on 32-bit systems.
self
.
check_conversion_to_int
(
-
boundary
-
1.0
)
self
.
check_conversion_to_int
(
-
boundary
-
1.0
+
2
*
epsilon
)
@
test_support
.
run_with_locale
(
'LC_NUMERIC'
,
'fr_FR'
,
'de_DE'
)
def
test_float_with_comma
(
self
):
# set locale to something that doesn't use '.' for the decimal point
...
...
Misc/NEWS
View file @
1492456e
...
...
@@ -9,6 +9,10 @@ What's New in Python 2.7.2?
Core and Builtins
-----------------
- Issue #11144: Ensure that int(a_float) returns an int whenever possible.
Previously, there were some corner cases where a long was returned even
though the result was within the range of an int.
- Issue #11675: multiprocessing.[Raw]Array objects created from an integer size
are now zeroed on creation. This matches the behaviour specified by the
documentation.
...
...
Objects/floatobject.c
View file @
1492456e
...
...
@@ -1035,14 +1035,17 @@ float_trunc(PyObject *v)
* happens if the double is too big to fit in a long. Some rare
* systems raise an exception then (RISCOS was mentioned as one,
* and someone using a non-default option on Sun also bumped into
* that). Note that checking for >= and <= LONG_{MIN,MAX} would
* still be vulnerable: if a long has more bits of precision than
* a double, casting MIN/MAX to double may yield an approximation,
* and if that's rounded up, then, e.g., wholepart=LONG_MAX+1 would
* yield true from the C expression wholepart<=LONG_MAX, despite
* that wholepart is actually greater than LONG_MAX.
* that). Note that checking for <= LONG_MAX is unsafe: if a long
* has more bits of precision than a double, casting LONG_MAX to
* double may yield an approximation, and if that's rounded up,
* then, e.g., wholepart=LONG_MAX+1 would yield true from the C
* expression wholepart<=LONG_MAX, despite that wholepart is
* actually greater than LONG_MAX. However, assuming a two's complement
* machine with no trap representation, LONG_MIN will be a power of 2 (and
* hence exactly representable as a double), and LONG_MAX = -1-LONG_MIN, so
* the comparisons with (double)LONG_MIN below should be safe.
*/
if
(
LONG_MIN
<
wholepart
&&
wholepart
<
LONG_MAX
)
{
if
(
(
double
)
LONG_MIN
<=
wholepart
&&
wholepart
<
-
(
double
)
LONG_MIN
)
{
const
long
aslong
=
(
long
)
wholepart
;
return
PyInt_FromLong
(
aslong
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment