Added a new NORMALIZE_NUMBERS option, which causes number literals in
the expected output to match corresponding number literals in the
actual output if their values are equal (to ten digits of precision).
diff --git a/Doc/lib/libdoctest.tex b/Doc/lib/libdoctest.tex
index 2635486..a30a432 100644
--- a/Doc/lib/libdoctest.tex
+++ b/Doc/lib/libdoctest.tex
@@ -581,6 +581,17 @@
 
 \end{datadesc}
 
+\begin{datadesc}{NORMALIZE_NUMBERS}
+    When specified, number literals in the expected output will match
+    corresponding number literals in the actual output if their values
+    are equal (to ten digits of precision).  For example, \code{1.1}
+    will match \code{1.1000000000000001}; and \code{1L} will match
+    \code{1} and \code{1.0}.  Currently, \constant{NORMALIZE_NUMBERS}
+    can fail to normalize numbers when used in conjunction with
+    ellipsis.  In particular, if an ellipsis marker matches one or
+    more numbers, then number normalization is not supported.
+\end{datadesc}
+
 \begin{datadesc}{COMPARISON_FLAGS}
     A bitmask or'ing together all the comparison flags above.
 \end{datadesc}
@@ -702,7 +713,7 @@
 
 \versionchanged[Constants \constant{DONT_ACCEPT_BLANKLINE},
     \constant{NORMALIZE_WHITESPACE}, \constant{ELLIPSIS},
-    \constant{IGNORE_EXCEPTION_DETAIL},
+    \constant{IGNORE_EXCEPTION_DETAIL}, \constant{NORMALIZE_NUMBERS},
     \constant{REPORT_UDIFF}, \constant{REPORT_CDIFF},
     \constant{REPORT_NDIFF}, \constant{REPORT_ONLY_FIRST_FAILURE},
     \constant{COMPARISON_FLAGS} and \constant{REPORTING_FLAGS}
@@ -740,6 +751,7 @@
 
 % Hey! What happened to Monty Python examples?
 % Tim: ask Guido -- it's his example!
+% doctest: ignore
 \begin{verbatim}
 >>> foo()
 {"Hermione": "hippogryph", "Harry": "broomstick"}
@@ -747,6 +759,7 @@
 
 is vulnerable!  One workaround is to do
 
+% doctest: ignore
 \begin{verbatim}
 >>> foo() == {"Hermione": "hippogryph", "Harry": "broomstick"}
 True
@@ -754,6 +767,7 @@
 
 instead.  Another is to do
 
+% doctest: ignore
 \begin{verbatim}
 >>> d = foo().items()
 >>> d.sort()
@@ -765,6 +779,7 @@
 
 Another bad idea is to print things that embed an object address, like
 
+% doctest: ignore
 \begin{verbatim}
 >>> id(1.0) # certain to fail some of the time
 7948648
@@ -776,6 +791,7 @@
 The \constant{ELLIPSIS} directive gives a nice approach for the last
 example:
 
+% doctest: ignore
 \begin{verbatim}
 >>> C() #doctest: +ELLIPSIS
 <__main__.C instance at 0x...>
@@ -785,6 +801,7 @@
 platforms, because Python defers to the platform C library for float
 formatting, and C libraries vary widely in quality here.
 
+% doctest: ignore
 \begin{verbatim}
 >>> 1./7  # risky
 0.14285714285714285
@@ -1618,6 +1635,7 @@
 
       Then an interactive Python session may look like this:
 
+% doctest: ignore
 \begin{verbatim}
 >>> import a, doctest
 >>> doctest.testmod(a)
diff --git a/Lib/doctest.py b/Lib/doctest.py
index 26a8914..dfd8bb9 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -55,6 +55,7 @@
     'NORMALIZE_WHITESPACE',
     'ELLIPSIS',
     'IGNORE_EXCEPTION_DETAIL',
+    'NORMALIZE_NUMBERS',
     'COMPARISON_FLAGS',
     'REPORT_UDIFF',
     'REPORT_CDIFF',
@@ -139,12 +140,14 @@
 NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE')
 ELLIPSIS = register_optionflag('ELLIPSIS')
 IGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL')
+NORMALIZE_NUMBERS = register_optionflag('NORMALIZE_NUMBERS')
 
 COMPARISON_FLAGS = (DONT_ACCEPT_TRUE_FOR_1 |
                     DONT_ACCEPT_BLANKLINE |
                     NORMALIZE_WHITESPACE |
                     ELLIPSIS |
-                    IGNORE_EXCEPTION_DETAIL)
+                    IGNORE_EXCEPTION_DETAIL |
+                    NORMALIZE_NUMBERS)
 
 REPORT_UDIFF = register_optionflag('REPORT_UDIFF')
 REPORT_CDIFF = register_optionflag('REPORT_CDIFF')
@@ -277,6 +280,72 @@
         if hasattr(self, "softspace"):
             del self.softspace
 
+# The number of digits of precision that must be equal for
+# NORMALIZE_NUMBERS to consider two numbers equal.
+_NORMALIZE_NUMBERS_PRECISION_THRESHOLD = 10
+
+# A regular expression that matches Python number literals.  This is
+# used by _normalize_numbers to look for numbers that should be
+# normalized.
+_NUMBER_LITERAL = re.compile(r'''
+    (\d+[.]\d*(?:[eE][-+]?\d+)?[jJ]? | # float (w/ digits left of ".")
+        [.]\d+(?:[eE][-+]?\d+)?[jJ]? | # float (no digits left of ".")
+     \d+      (?:[eE][-+]?\d+) [jJ]? | # float (no ".", exponent only)
+     \d                        [jJ]  | # float (no ".", imaginary only)
+     0[xX]\d+[lL]?                   | # hexint
+     0[0-7]*[lL]?                    | # octint or zero
+     \d+[lL]?                        ) # decint
+     ''', re.VERBOSE)
+
+def _normalize_numbers(want, got):
+    """
+    If all the numbers in `want` and `got` match (one-for-one), then
+    return a new version of `got` with the exact number strings from
+    `want` spliced in.  Two numbers match if `str` of their float
+    values are equal.  (I.e., `x` matches `y` if
+    `str(float(x))==str(float(y))`).
+    """
+    want_pieces = _NUMBER_LITERAL.split(want)
+    got_pieces = _NUMBER_LITERAL.split(got)
+
+    # If they don't have the same number of numbers, fail immediately.
+    if len(want_pieces) != len(got_pieces):
+        return got
+
+    # If any individual numbers don't match, then fail.
+    for i in range(1, len(got_pieces), 2):
+        w, g = eval(want_pieces[i]), eval(got_pieces[i])
+        if not _numbers_match(w, g):
+            return got
+
+    # Success; replace numbers in got w/ numbers from want.
+    for i in range(1, len(got_pieces), 2):
+        got_pieces[i] = want_pieces[i]
+    return ''.join(got_pieces)
+
+def _numbers_match(x, y):
+    """
+    A helper function for _normalize_numbers, that returns true if the
+    numbers `x` and `y` are close enough to match for NORMALIZE_NUMBERS.
+    """
+    # Equal numbers match.
+    if x == y:
+        return True
+    # Split up complex numbers into real & imag.
+    if isinstance(x, complex):
+        return (isinstance(y, complex) and
+                _numbers_match(x.real, y.real) and
+                _numbers_match(x.imag, y.imag))
+    # If the signs are different, they don't match.
+    if x*y < 0:
+        return False
+    # If one is zero and the other isn't, they don't match.
+    if x==0 or y==0:
+        return False
+    # They're not exactly equal, but are they close enough?
+    threshold = 10**-_NORMALIZE_NUMBERS_PRECISION_THRESHOLD
+    return (abs(x-y) / min(abs(x), abs(y))) < threshold
+
 # Worst-case linear-time ellipsis matching.
 def _ellipsis_match(want, got):
     """
@@ -1503,6 +1572,13 @@
             if got == want:
                 return True
 
+        # This flag causes doctest to treat numbers that are within a
+        # small threshold as if they are equal.
+        if optionflags & NORMALIZE_NUMBERS:
+            got = _normalize_numbers(want, got)
+            if got == want:
+                return True
+
         # The ELLIPSIS flag says to let the sequence "..." in `want`
         # match any substring in `got`.
         if optionflags & ELLIPSIS:
@@ -1783,6 +1859,7 @@
         NORMALIZE_WHITESPACE
         ELLIPSIS
         IGNORE_EXCEPTION_DETAIL
+        NORMALIZE_NUMBERS
         REPORT_UDIFF
         REPORT_CDIFF
         REPORT_NDIFF
@@ -1905,6 +1982,7 @@
         NORMALIZE_WHITESPACE
         ELLIPSIS
         IGNORE_EXCEPTION_DETAIL
+        NORMALIZE_NUMBERS
         REPORT_UDIFF
         REPORT_CDIFF
         REPORT_NDIFF
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py
index d17ca1a..eb0b10c 100644
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -1032,6 +1032,107 @@
     [0,   1,  2,  3,  4,  5,  6,  7,  8,  9,
     10,  11, 12, 13, 14, 15, 16, 17, 18, 19]
 
+The NORMALIZE_NUMBERS flag causes numbers that are equal (to
+approximately 10 decimal places) but formatted differently to match.
+
+    >>> def f(x): '''
+    ...     Numbers will match if they are exactly equal:
+    ...
+    ...     >>> print 1.1, 'intervening text', 1L # should match
+    ...     1.1 intervening text 1L
+    ...     >>> print 1.0j, 22, 22.0, 1, 1e1      # should match
+    ...     1j 22.0 22 1 10.0
+    ...
+    ...     Numbers will match if they are equal to 14 digits of
+    ...     precision:
+    ...
+    ...     >>> 2.00000000001                      # should match
+    ...     1.99999999999
+    ...     >>> 2.000000001                        # should not match
+    ...     1.999999999
+    ...     >>> 2.00000000001e10                   # should match
+    ...     1.99999999999e10
+    ...     >>> 2.000000001e10                     # should not match
+    ...     1.999999999e10
+    ...     '''
+
+    >>> # Without the flag:
+    >>> test = doctest.DocTestFinder().find(f)[0]
+    >>> doctest.DocTestRunner(verbose=False).run(test)
+    ... # doctest: +ELLIPSIS
+    **********************************************************************
+    File ..., line 4, in f
+    Failed example:
+        print 1.1, 'intervening text', 1L # should match
+    Expected:
+        1.1 intervening text 1L
+    Got:
+        1.1 intervening text 1
+    **********************************************************************
+    File ..., line 6, in f
+    Failed example:
+        print 1.0j, 22, 22.0, 1, 1e1      # should match
+    Expected:
+        1j 22.0 22 1 10.0
+    Got:
+        1j 22 22.0 1 10.0
+    **********************************************************************
+    File ..., line 12, in f
+    Failed example:
+        2.00000000001                      # should match
+    Expected:
+        1.99999999999
+    Got:
+        2.00000000001
+    **********************************************************************
+    File ..., line 14, in f
+    Failed example:
+        2.000000001                        # should not match
+    Expected:
+        1.999999999
+    Got:
+        2.0000000010000001
+    **********************************************************************
+    File ..., line 16, in f
+    Failed example:
+        2.00000000001e10                   # should match
+    Expected:
+        1.99999999999e10
+    Got:
+        20000000000.099998
+    **********************************************************************
+    File ..., line 18, in f
+    Failed example:
+        2.000000001e10                     # should not match
+    Expected:
+        1.999999999e10
+    Got:
+        20000000010.0
+    (6, 6)
+
+    >>> # With the flag:
+    >>> test = doctest.DocTestFinder().find(f)[0]
+    >>> flags = doctest.NORMALIZE_NUMBERS
+    >>> doctest.DocTestRunner(verbose=False, optionflags=flags).run(test)
+    ... # doctest: +ELLIPSIS
+    **********************************************************************
+    File ..., line 14, in f
+    Failed example:
+        2.000000001                        # should not match
+    Expected:
+        1.999999999
+    Got:
+        2.0000000010000001
+    **********************************************************************
+    File ..., line 18, in f
+    Failed example:
+        2.000000001e10                     # should not match
+    Expected:
+        1.999999999e10
+    Got:
+        20000000010.0
+    (2, 6)
+
 The ELLIPSIS flag causes ellipsis marker ("...") in the expected
 output to match any substring in the actual output: