MCPcopy Index your code
hub / github.com/python/cpython / strtod

Function strtod

Lib/test/test_strtod.py:27–82  ·  view source on GitHub ↗

Convert a finite decimal string to a hex string representing an IEEE 754 binary64 float. Return 'inf' or '-inf' on overflow. This function makes no use of floating-point arithmetic at any stage.

(s, mant_dig=53, min_exp = -1021, max_exp = 1024)

Source from the content-addressed store, hash-verified

25# Pure Python version of correctly rounded string->float conversion.
26# Avoids any use of floating-point by returning the result as a hex string.
27def strtod(s, mant_dig=53, min_exp = -1021, max_exp = 1024):
28 """Convert a finite decimal string to a hex string representing an
29 IEEE 754 binary64 float. Return 'inf' or '-inf' on overflow.
30 This function makes no use of floating-point arithmetic at any
31 stage."""
32
33 # parse string into a pair of integers 'a' and 'b' such that
34 # abs(decimal value) = a/b, along with a boolean 'negative'.
35 m = strtod_parser(s)
36 if m is None:
37 raise ValueError('invalid numeric string')
38 fraction = m.group('frac') or ''
39 intpart = int(m.group('int') + fraction)
40 exp = int(m.group('exp') or '0') - len(fraction)
41 negative = m.group('sign') == '-'
42 a, b = intpart*10**max(exp, 0), 10**max(0, -exp)
43
44 # quick return for zeros
45 if not a:
46 return '-0x0.0p+0' if negative else '0x0.0p+0'
47
48 # compute exponent e for result; may be one too small in the case
49 # that the rounded value of a/b lies in a different binade from a/b
50 d = a.bit_length() - b.bit_length()
51 d += (a >> d if d >= 0 else a << -d) >= b
52 e = max(d, min_exp) - mant_dig
53
54 # approximate a/b by number of the form q * 2**e; adjust e if necessary
55 a, b = a << max(-e, 0), b << max(e, 0)
56 q, r = divmod(a, b)
57 if 2*r > b or 2*r == b and q & 1:
58 q += 1
59 if q.bit_length() == mant_dig+1:
60 q //= 2
61 e += 1
62
63 # double check that (q, e) has the right form
64 assert q.bit_length() <= mant_dig and e >= min_exp - mant_dig
65 assert q.bit_length() == mant_dig or e == min_exp - mant_dig
66
67 # check for overflow and underflow
68 if e + q.bit_length() > max_exp:
69 return '-inf' if negative else 'inf'
70 if not q:
71 return '-0x0.0p+0' if negative else '0x0.0p+0'
72
73 # for hex representation, shift so # bits after point is a multiple of 4
74 hexdigs = 1 + (mant_dig-2)//4
75 shift = 3 - (mant_dig-2)%4
76 q, e = q << shift, e - shift
77 return '{}0x{:x}.{:0{}x}p{:+d}'.format(
78 '-' if negative else '',
79 q // 16**hexdigs,
80 q % 16**hexdigs,
81 hexdigs,
82 e + 4*hexdigs)
83
84TEST_SIZE = 10

Callers 1

check_strtodMethod · 0.85

Calls 3

bit_lengthMethod · 0.80
groupMethod · 0.45
formatMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…