Back to index

python3.2  3.2.2
Public Member Functions
test.test_strtod.StrtodTests Class Reference

List of all members.

Public Member Functions

def check_strtod
def test_short_halfway_cases
def test_halfway_cases
def test_boundaries
def test_underflow_boundary
def test_bigcomp
def test_parsing
def test_particular

Detailed Description

Definition at line 86 of file test_strtod.py.


Member Function Documentation

Compare the result of Python's builtin correctly rounded
string->float conversion (using float) to a pure Python
correctly rounded string->float implementation.  Fail if the
two methods give different results.

Definition at line 87 of file test_strtod.py.

00087 
00088     def check_strtod(self, s):
00089         """Compare the result of Python's builtin correctly rounded
00090         string->float conversion (using float) to a pure Python
00091         correctly rounded string->float implementation.  Fail if the
00092         two methods give different results."""
00093 
00094         try:
00095             fs = float(s)
00096         except OverflowError:
00097             got = '-inf' if s[0] == '-' else 'inf'
00098         except MemoryError:
00099             got = 'memory error'
00100         else:
00101             got = fs.hex()
00102         expected = strtod(s)
00103         self.assertEqual(expected, got,
00104                          "Incorrectly rounded str->float conversion for {}: "
00105                          "expected {}, got {}".format(s, expected, got))

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 206 of file test_strtod.py.

00206 
00207     def test_bigcomp(self):
00208         for ndigs in 5, 10, 14, 15, 16, 17, 18, 19, 20, 40, 41, 50:
00209             dig10 = 10**ndigs
00210             for i in range(10 * TEST_SIZE):
00211                 digits = random.randrange(dig10)
00212                 exponent = random.randrange(-400, 400)
00213                 s = '{}e{}'.format(digits, exponent)
00214                 self.check_strtod(s)

Here is the call graph for this function:

Definition at line 175 of file test_strtod.py.

00175 
00176     def test_boundaries(self):
00177         # boundaries expressed as triples (n, e, u), where
00178         # n*10**e is an approximation to the boundary value and
00179         # u*10**e is 1ulp
00180         boundaries = [
00181             (10000000000000000000, -19, 1110),   # a power of 2 boundary (1.0)
00182             (17976931348623159077, 289, 1995),   # overflow boundary (2.**1024)
00183             (22250738585072013831, -327, 4941),  # normal/subnormal (2.**-1022)
00184             (0, -327, 4941),                     # zero
00185             ]
00186         for n, e, u in boundaries:
00187             for j in range(1000):
00188                 digits = n + random.randrange(-3*u, 3*u)
00189                 exponent = e
00190                 s = '{}e{}'.format(digits, exponent)
00191                 self.check_strtod(s)
00192                 n *= 10
00193                 u *= 10
00194                 e -= 1

Here is the call graph for this function:

Definition at line 149 of file test_strtod.py.

00149 
00150     def test_halfway_cases(self):
00151         # test halfway cases for the round-half-to-even rule
00152         for i in range(100 * TEST_SIZE):
00153             # bit pattern for a random finite positive (or +0.0) float
00154             bits = random.randrange(2047*2**52)
00155 
00156             # convert bit pattern to a number of the form m * 2**e
00157             e, m = divmod(bits, 2**52)
00158             if e:
00159                 m, e = m + 2**52, e - 1
00160             e -= 1074
00161 
00162             # add 0.5 ulps
00163             m, e = 2*m + 1, e - 1
00164 
00165             # convert to a decimal string
00166             if e >= 0:
00167                 digits = m << e
00168                 exponent = 0
00169             else:
00170                 # m * 2**e = (m * 5**-e) * 10**e
00171                 digits = m * 5**-e
00172                 exponent = e
00173             s = '{}e{}'.format(digits, exponent)
00174             self.check_strtod(s)

Here is the call graph for this function:

Definition at line 215 of file test_strtod.py.

00215 
00216     def test_parsing(self):
00217         # make '0' more likely to be chosen than other digits
00218         digits = '000000123456789'
00219         signs = ('+', '-', '')
00220 
00221         # put together random short valid strings
00222         # \d*[.\d*]?e
00223         for i in range(1000):
00224             for j in range(TEST_SIZE):
00225                 s = random.choice(signs)
00226                 intpart_len = random.randrange(5)
00227                 s += ''.join(random.choice(digits) for _ in range(intpart_len))
00228                 if random.choice([True, False]):
00229                     s += '.'
00230                     fracpart_len = random.randrange(5)
00231                     s += ''.join(random.choice(digits)
00232                                  for _ in range(fracpart_len))
00233                 else:
00234                     fracpart_len = 0
00235                 if random.choice([True, False]):
00236                     s += random.choice(['e', 'E'])
00237                     s += random.choice(signs)
00238                     exponent_len = random.randrange(1, 4)
00239                     s += ''.join(random.choice(digits)
00240                                  for _ in range(exponent_len))
00241 
00242                 if intpart_len + fracpart_len:
00243                     self.check_strtod(s)
00244                 else:
00245                     try:
00246                         float(s)
00247                     except ValueError:
00248                         pass
00249                     else:
00250                         assert False, "expected ValueError"

Here is the call graph for this function:

Definition at line 251 of file test_strtod.py.

00251 
00252     def test_particular(self):
00253         # inputs that produced crashes or incorrectly rounded results with
00254         # previous versions of dtoa.c, for various reasons
00255         test_strings = [
00256             # issue 7632 bug 1, originally reported failing case
00257             '2183167012312112312312.23538020374420446192e-370',
00258             # 5 instances of issue 7632 bug 2
00259             '12579816049008305546974391768996369464963024663104e-357',
00260             '17489628565202117263145367596028389348922981857013e-357',
00261             '18487398785991994634182916638542680759613590482273e-357',
00262             '32002864200581033134358724675198044527469366773928e-358',
00263             '94393431193180696942841837085033647913224148539854e-358',
00264             '73608278998966969345824653500136787876436005957953e-358',
00265             '64774478836417299491718435234611299336288082136054e-358',
00266             '13704940134126574534878641876947980878824688451169e-357',
00267             '46697445774047060960624497964425416610480524760471e-358',
00268             # failing case for bug introduced by METD in r77451 (attempted
00269             # fix for issue 7632, bug 2), and fixed in r77482.
00270             '28639097178261763178489759107321392745108491825303e-311',
00271             # two numbers demonstrating a flaw in the bigcomp 'dig == 0'
00272             # correction block (issue 7632, bug 3)
00273             '1.00000000000000001e44',
00274             '1.0000000000000000100000000000000000000001e44',
00275             # dtoa.c bug for numbers just smaller than a power of 2 (issue
00276             # 7632, bug 4)
00277             '99999999999999994487665465554760717039532578546e-47',
00278             # failing case for off-by-one error introduced by METD in
00279             # r77483 (dtoa.c cleanup), fixed in r77490
00280             '965437176333654931799035513671997118345570045914469' #...
00281             '6213413350821416312194420007991306908470147322020121018368e0',
00282             # incorrect lsb detection for round-half-to-even when
00283             # bc->scale != 0 (issue 7632, bug 6).
00284             '104308485241983990666713401708072175773165034278685' #...
00285             '682646111762292409330928739751702404658197872319129' #...
00286             '036519947435319418387839758990478549477777586673075' #...
00287             '945844895981012024387992135617064532141489278815239' #...
00288             '849108105951619997829153633535314849999674266169258' #...
00289             '928940692239684771590065027025835804863585454872499' #...
00290             '320500023126142553932654370362024104462255244034053' #...
00291             '203998964360882487378334860197725139151265590832887' #...
00292             '433736189468858614521708567646743455601905935595381' #...
00293             '852723723645799866672558576993978025033590728687206' #...
00294             '296379801363024094048327273913079612469982585674824' #...
00295             '156000783167963081616214710691759864332339239688734' #...
00296             '656548790656486646106983450809073750535624894296242' #...
00297             '072010195710276073042036425579852459556183541199012' #...
00298             '652571123898996574563824424330960027873516082763671875e-1075',
00299             # demonstration that original fix for issue 7632 bug 1 was
00300             # buggy; the exit condition was too strong
00301             '247032822920623295e-341',
00302             # demonstrate similar problem to issue 7632 bug1: crash
00303             # with 'oversized quotient in quorem' message.
00304             '99037485700245683102805043437346965248029601286431e-373',
00305             '99617639833743863161109961162881027406769510558457e-373',
00306             '98852915025769345295749278351563179840130565591462e-372',
00307             '99059944827693569659153042769690930905148015876788e-373',
00308             '98914979205069368270421829889078356254059760327101e-372',
00309             # issue 7632 bug 5: the following 2 strings convert differently
00310             '1000000000000000000000000000000000000000e-16',
00311             '10000000000000000000000000000000000000000e-17',
00312             # issue 7632 bug 7
00313             '991633793189150720000000000000000000000000000000000000000e-33',
00314             # And another, similar, failing halfway case
00315             '4106250198039490000000000000000000000000000000000000000e-38',
00316             # issue 7632 bug 8:  the following produced 10.0
00317             '10.900000000000000012345678912345678912345',
00318 
00319             # two humongous values from issue 7743
00320             '116512874940594195638617907092569881519034793229385' #...
00321             '228569165191541890846564669771714896916084883987920' #...
00322             '473321268100296857636200926065340769682863349205363' #...
00323             '349247637660671783209907949273683040397979984107806' #...
00324             '461822693332712828397617946036239581632976585100633' #...
00325             '520260770761060725403904123144384571612073732754774' #...
00326             '588211944406465572591022081973828448927338602556287' #...
00327             '851831745419397433012491884869454462440536895047499' #...
00328             '436551974649731917170099387762871020403582994193439' #...
00329             '761933412166821484015883631622539314203799034497982' #...
00330             '130038741741727907429575673302461380386596501187482' #...
00331             '006257527709842179336488381672818798450229339123527' #...
00332             '858844448336815912020452294624916993546388956561522' #...
00333             '161875352572590420823607478788399460162228308693742' #...
00334             '05287663441403533948204085390898399055004119873046875e-1075',
00335 
00336             '525440653352955266109661060358202819561258984964913' #...
00337             '892256527849758956045218257059713765874251436193619' #...
00338             '443248205998870001633865657517447355992225852945912' #...
00339             '016668660000210283807209850662224417504752264995360' #...
00340             '631512007753855801075373057632157738752800840302596' #...
00341             '237050247910530538250008682272783660778181628040733' #...
00342             '653121492436408812668023478001208529190359254322340' #...
00343             '397575185248844788515410722958784640926528544043090' #...
00344             '115352513640884988017342469275006999104519620946430' #...
00345             '818767147966495485406577703972687838176778993472989' #...
00346             '561959000047036638938396333146685137903018376496408' #...
00347             '319705333868476925297317136513970189073693314710318' #...
00348             '991252811050501448326875232850600451776091303043715' #...
00349             '157191292827614046876950225714743118291034780466325' #...
00350             '085141343734564915193426994587206432697337118211527' #...
00351             '278968731294639353354774788602467795167875117481660' #...
00352             '4738791256853675690543663283782215866825e-1180',
00353 
00354             # exercise exit conditions in bigcomp comparison loop
00355             '2602129298404963083833853479113577253105939995688e2',
00356             '260212929840496308383385347911357725310593999568896e0',
00357             '26021292984049630838338534791135772531059399956889601e-2',
00358             '260212929840496308383385347911357725310593999568895e0',
00359             '260212929840496308383385347911357725310593999568897e0',
00360             '260212929840496308383385347911357725310593999568996e0',
00361             '260212929840496308383385347911357725310593999568866e0',
00362             # 2**53
00363             '9007199254740992.00',
00364             # 2**1024 - 2**970:  exact overflow boundary.  All values
00365             # smaller than this should round to something finite;  any value
00366             # greater than or equal to this one overflows.
00367             '179769313486231580793728971405303415079934132710037' #...
00368             '826936173778980444968292764750946649017977587207096' #...
00369             '330286416692887910946555547851940402630657488671505' #...
00370             '820681908902000708383676273854845817711531764475730' #...
00371             '270069855571366959622842914819860834936475292719074' #...
00372             '168444365510704342711559699508093042880177904174497792',
00373             # 2**1024 - 2**970 - tiny
00374             '179769313486231580793728971405303415079934132710037' #...
00375             '826936173778980444968292764750946649017977587207096' #...
00376             '330286416692887910946555547851940402630657488671505' #...
00377             '820681908902000708383676273854845817711531764475730' #...
00378             '270069855571366959622842914819860834936475292719074' #...
00379             '168444365510704342711559699508093042880177904174497791.999',
00380             # 2**1024 - 2**970 + tiny
00381             '179769313486231580793728971405303415079934132710037' #...
00382             '826936173778980444968292764750946649017977587207096' #...
00383             '330286416692887910946555547851940402630657488671505' #...
00384             '820681908902000708383676273854845817711531764475730' #...
00385             '270069855571366959622842914819860834936475292719074' #...
00386             '168444365510704342711559699508093042880177904174497792.001',
00387             # 1 - 2**-54, +-tiny
00388             '999999999999999944488848768742172978818416595458984375e-54',
00389             '9999999999999999444888487687421729788184165954589843749999999e-54',
00390             '9999999999999999444888487687421729788184165954589843750000001e-54',
00391             # Value found by Rick Regan that gives a result of 2**-968
00392             # under Gay's dtoa.c (as of Nov 04, 2010);  since fixed.
00393             # (Fixed some time ago in Python's dtoa.c.)
00394             '0.0000000000000000000000000000000000000000100000000' #...
00395             '000000000576129113423785429971690421191214034235435' #...
00396             '087147763178149762956868991692289869941246658073194' #...
00397             '51982237978882039897143840789794921875',
00398             ]
00399         for s in test_strings:
00400             self.check_strtod(s)

Here is the call graph for this function:

Definition at line 106 of file test_strtod.py.

00106 
00107     def test_short_halfway_cases(self):
00108         # exact halfway cases with a small number of significant digits
00109         for k in 0, 5, 10, 15, 20:
00110             # upper = smallest integer >= 2**54/5**k
00111             upper = -(-2**54//5**k)
00112             # lower = smallest odd number >= 2**53/5**k
00113             lower = -(-2**53//5**k)
00114             if lower % 2 == 0:
00115                 lower += 1
00116             for i in range(TEST_SIZE):
00117                 # Select a random odd n in [2**53/5**k,
00118                 # 2**54/5**k). Then n * 10**k gives a halfway case
00119                 # with small number of significant digits.
00120                 n, e = random.randrange(lower, upper, 2), k
00121 
00122                 # Remove any additional powers of 5.
00123                 while n % 5 == 0:
00124                     n, e = n // 5, e + 1
00125                 assert n % 10 in (1, 3, 7, 9)
00126 
00127                 # Try numbers of the form n * 2**p2 * 10**e, p2 >= 0,
00128                 # until n * 2**p2 has more than 20 significant digits.
00129                 digits, exponent = n, e
00130                 while digits < 10**20:
00131                     s = '{}e{}'.format(digits, exponent)
00132                     self.check_strtod(s)
00133                     # Same again, but with extra trailing zeros.
00134                     s = '{}e{}'.format(digits * 10**40, exponent - 40)
00135                     self.check_strtod(s)
00136                     digits *= 2
00137 
00138                 # Try numbers of the form n * 5**p2 * 10**(e - p5), p5
00139                 # >= 0, with n * 5**p5 < 10**20.
00140                 digits, exponent = n, e
00141                 while digits < 10**20:
00142                     s = '{}e{}'.format(digits, exponent)
00143                     self.check_strtod(s)
00144                     # Same again, but with extra trailing zeros.
00145                     s = '{}e{}'.format(digits * 10**40, exponent - 40)
00146                     self.check_strtod(s)
00147                     digits *= 5
00148                     exponent -= 1

Here is the call graph for this function:

Definition at line 195 of file test_strtod.py.

00195 
00196     def test_underflow_boundary(self):
00197         # test values close to 2**-1075, the underflow boundary; similar
00198         # to boundary_tests, except that the random error doesn't scale
00199         # with n
00200         for exponent in range(-400, -320):
00201             base = 10**-exponent // 2**1075
00202             for j in range(TEST_SIZE):
00203                 digits = base + random.randrange(-1000, 1000)
00204                 s = '{}e{}'.format(digits, exponent)
00205                 self.check_strtod(s)

Here is the call graph for this function:


The documentation for this class was generated from the following file: