4b9ebf41f4
Closes #837
752 lines
28 KiB
Python
752 lines
28 KiB
Python
import random
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
from mpmath import fp, inf, mp, nan, ninf, workdps
|
|
|
|
|
|
def random_fmt():
|
|
'''
|
|
This helper generates valid random format strings.
|
|
'''
|
|
|
|
fmt_str = '{:'
|
|
|
|
# fill_char and align
|
|
n = random.randint(0, 2)
|
|
if n == 0:
|
|
fmt_str += random.choice('z;clxvjqwer') + random.choice('<^>=')
|
|
skip_0_padding = True
|
|
elif n == 1:
|
|
fmt_str += random.choice('<^>=')
|
|
skip_0_padding = True
|
|
else:
|
|
skip_0_padding = False
|
|
|
|
# sign character
|
|
n = random.randint(0, 1)
|
|
if n == 1:
|
|
fmt_str += random.choice('-+ ')
|
|
|
|
# no_neg_0 (not used yet.)
|
|
if sys.version_info[:3] > (3, 11):
|
|
n = random.randint(0, 1)
|
|
if n == 1:
|
|
fmt_str += 'z'
|
|
|
|
# alternate mode
|
|
n = random.randint(0, 1)
|
|
if n == 1:
|
|
fmt_str += '#'
|
|
|
|
# pad with 0s
|
|
n = random.randint(0, 1)
|
|
skip_thousand_separators = False
|
|
if n == 1 and not skip_0_padding:
|
|
fmt_str += '0'
|
|
skip_thousand_separators = True
|
|
|
|
# Width
|
|
n = random.randint(0, 2)
|
|
if n > 0:
|
|
fmt_str += str(random.randint(1, 40))
|
|
|
|
# grouping character (thousand_separators)
|
|
n = random.randint(0, 1)
|
|
if n == 1 and not skip_thousand_separators:
|
|
fmt_str += random.choice(',_')
|
|
|
|
# Precision
|
|
n = random.randint(0, 2)
|
|
if n > 0:
|
|
fmt_str += '.' + str(random.randint(1, 40))
|
|
|
|
# Type
|
|
fmt_str += random.choice('fFgGeE%')
|
|
fmt_str += '}'
|
|
|
|
return fmt_str
|
|
|
|
|
|
def test_mpf_fmt_cpython():
|
|
'''
|
|
These tests assure that mpf.__format__ yields the same result as regular
|
|
float.__format__, when dps is default.
|
|
'''
|
|
|
|
# 'f' code formatting.
|
|
|
|
# zeros
|
|
assert f'{mp.mpf(0):.0f}' == '0'
|
|
assert f'{mp.mpf(0):.1f}' == '0.0'
|
|
assert f'{mp.mpf(0):.2f}' == '0.00'
|
|
assert f'{mp.mpf(0):.3f}' == '0.000'
|
|
assert f'{mp.mpf(0):.50f}' == '0.00000000000000000000000000000000000000000000000000'
|
|
|
|
# nan, infs
|
|
assert f'{inf:f}' == 'inf'
|
|
assert f'{inf:+f}' == '+inf'
|
|
assert f'{inf:F}' == 'INF'
|
|
assert f'{inf:+F}' == '+INF'
|
|
|
|
assert f'{ninf:f}' == '-inf'
|
|
assert f'{ninf:+f}' == '-inf'
|
|
assert f'{ninf:F}' == '-INF'
|
|
assert f'{ninf:+F}' == '-INF'
|
|
|
|
assert f'{nan:f}' == 'nan'
|
|
assert f'{nan:+f}' == '+nan'
|
|
assert f'{nan:F}' == 'NAN'
|
|
assert f'{nan:+F}' == '+NAN'
|
|
|
|
# precision 0; result should never include a .
|
|
assert f'{mp.mpf(1.5):.0f}' == '2'
|
|
assert f'{mp.mpf(2.5):.0f}' == '2'
|
|
assert f'{mp.mpf(3.5):.0f}' == '4'
|
|
assert f'{mp.mpf(0.0):.0f}' == '0'
|
|
assert f'{mp.mpf(0.1):.0f}' == '0'
|
|
assert f'{mp.mpf(0.001):.0f}' == '0'
|
|
assert f'{mp.mpf(10.0):.0f}' == '10'
|
|
assert f'{mp.mpf(10.1):.0f}' == '10'
|
|
assert f'{mp.mpf(10.01):.0f}' == '10'
|
|
assert f'{mp.mpf(123.456):.0f}' == '123'
|
|
assert f'{mp.mpf(1234.56):.0f}' == '1235'
|
|
assert f'{mp.mpf(1e49):.0f}' == '9999999999999999464902769475481793196872414789632'
|
|
assert f'{mp.mpf(9.9999999999999987e+49):.0f}' == '99999999999999986860582406952576489172979654066176'
|
|
assert f'{mp.mpf(1e50):.0f}' == '100000000000000007629769841091887003294964970946560'
|
|
|
|
# precision 1
|
|
assert f'{mp.mpf(0.0001):.1f}' == '0.0'
|
|
assert f'{mp.mpf(0.001):.1f}' == '0.0'
|
|
assert f'{mp.mpf(0.01):.1f}' == '0.0'
|
|
assert f'{mp.mpf(0.04):.1f}' == '0.0'
|
|
assert f'{mp.mpf(0.06):.1f}' == '0.1'
|
|
assert f'{mp.mpf(0.25):.1f}' == '0.2'
|
|
assert f'{mp.mpf(0.75):.1f}' == '0.8'
|
|
assert f'{mp.mpf(1.4):.1f}' == '1.4'
|
|
assert f'{mp.mpf(1.5):.1f}' == '1.5'
|
|
assert f'{mp.mpf(10.0):.1f}' == '10.0'
|
|
assert f'{mp.mpf(1000.03):.1f}' == '1000.0'
|
|
assert f'{mp.mpf(1234.5678):.1f}' == '1234.6'
|
|
assert f'{mp.mpf(1234.7499):.1f}' == '1234.7'
|
|
assert f'{mp.mpf(1234.75):.1f}' == '1234.8'
|
|
|
|
# precision 2
|
|
assert f'{mp.mpf(0.0001):.2f}' == '0.00'
|
|
assert f'{mp.mpf(0.001):.2f}' == '0.00'
|
|
assert f'{mp.mpf(0.004999):.2f}' == '0.00'
|
|
assert f'{mp.mpf(0.005001):.2f}' == '0.01'
|
|
assert f'{mp.mpf(0.01):.2f}' == '0.01'
|
|
assert f'{mp.mpf(0.125):.2f}' == '0.12'
|
|
assert f'{mp.mpf(0.375):.2f}' == '0.38'
|
|
assert f'{mp.mpf(1234500):.2f}' == '1234500.00'
|
|
assert f'{mp.mpf(1234560):.2f}' == '1234560.00'
|
|
assert f'{mp.mpf(1234567):.2f}' == '1234567.00'
|
|
assert f'{mp.mpf(1234567.8):.2f}' == '1234567.80'
|
|
assert f'{mp.mpf(1234567.89):.2f}' == '1234567.89'
|
|
assert f'{mp.mpf(1234567.891):.2f}' == '1234567.89'
|
|
assert f'{mp.mpf(1234567.8912):.2f}' == '1234567.89'
|
|
|
|
# alternate form always includes a decimal point. This only
|
|
# makes a difference when the precision is 0.
|
|
assert f'{mp.mpf(0):#.0f}' == '0.'
|
|
assert f'{mp.mpf(0):#.1f}' == '0.0'
|
|
assert f'{mp.mpf(1.5):#.0f}' == '2.'
|
|
assert f'{mp.mpf(2.5):#.0f}' == '2.'
|
|
assert f'{mp.mpf(10.1):#.0f}' == '10.'
|
|
assert f'{mp.mpf(1234.56):#.0f}' == '1235.'
|
|
assert f'{mp.mpf(1.4):#.1f}' == '1.4'
|
|
assert f'{mp.mpf(0.375):#.2f}' == '0.38'
|
|
|
|
# if precision is omitted it defaults to 6
|
|
assert f'{mp.mpf(0):f}' == '0.000000'
|
|
assert f'{mp.mpf(1230000):f}' == '1230000.000000'
|
|
assert f'{mp.mpf(1234567):f}' == '1234567.000000'
|
|
assert f'{mp.mpf(123.4567):f}' == '123.456700'
|
|
assert f'{mp.mpf(1.23456789):f}' == '1.234568'
|
|
assert f'{mp.mpf(0.00012):f}' == '0.000120'
|
|
assert f'{mp.mpf(0.000123):f}' == '0.000123'
|
|
assert f'{mp.mpf(0.00012345):f}' == '0.000123'
|
|
assert f'{mp.mpf(0.000001):f}' == '0.000001'
|
|
assert f'{mp.mpf(0.0000005001):f}' == '0.000001'
|
|
assert f'{mp.mpf(0.0000004999):f}' == '0.000000'
|
|
|
|
# 'e' code formatting with explicit precision (>= 0). Output should
|
|
# always have exactly the number of places after the point that were
|
|
# requested.
|
|
|
|
# zeros
|
|
assert f'{mp.mpf(0):.0e}' == '0e+00'
|
|
assert f'{mp.mpf(0):.1e}' == '0.0e+00'
|
|
assert f'{mp.mpf(0):.2e}' == '0.00e+00'
|
|
assert f'{mp.mpf(0):.10e}' == '0.0000000000e+00'
|
|
assert f'{mp.mpf(0):.50e}' == '0.00000000000000000000000000000000000000000000000000e+00'
|
|
|
|
# nan, infs
|
|
assert f'{inf:e}' == 'inf'
|
|
assert f'{inf:+e}' == '+inf'
|
|
assert f'{inf:E}' == 'INF'
|
|
assert f'{inf:+E}' == '+INF'
|
|
|
|
assert f'{ninf:e}' == '-inf'
|
|
assert f'{ninf:+e}' == '-inf'
|
|
assert f'{ninf:E}' == '-INF'
|
|
assert f'{ninf:+E}' == '-INF'
|
|
|
|
assert f'{nan:e}' == 'nan'
|
|
assert f'{nan:+e}' == '+nan'
|
|
assert f'{nan:E}' == 'NAN'
|
|
assert f'{nan:+E}' == '+NAN'
|
|
|
|
# precision 0. no decimal point in the output
|
|
assert f'{mp.mpf(0.01):.0e}' == '1e-02'
|
|
assert f'{mp.mpf(0.1):.0e}' == '1e-01'
|
|
assert f'{mp.mpf(1):.0e}' == '1e+00'
|
|
assert f'{mp.mpf(10):.0e}' == '1e+01'
|
|
assert f'{mp.mpf(100):.0e}' == '1e+02'
|
|
assert f'{mp.mpf(0.012):.0e}' == '1e-02'
|
|
assert f'{mp.mpf(0.12):.0e}' == '1e-01'
|
|
assert f'{mp.mpf(1.2):.0e}' == '1e+00'
|
|
assert f'{mp.mpf(12):.0e}' == '1e+01'
|
|
assert f'{mp.mpf(120):.0e}' == '1e+02'
|
|
assert f'{mp.mpf(123.456):.0e}' == '1e+02'
|
|
assert f'{mp.mpf(0.000123456):.0e}' == '1e-04'
|
|
assert f'{mp.mpf(123456000):.0e}' == '1e+08'
|
|
assert f'{mp.mpf(0.5):.0e}' == '5e-01'
|
|
assert f'{mp.mpf(1.4):.0e}' == '1e+00'
|
|
assert f'{mp.mpf(1.5):.0e}' == '2e+00'
|
|
assert f'{mp.mpf(1.6):.0e}' == '2e+00'
|
|
assert f'{mp.mpf(2.4999999):.0e}' == '2e+00'
|
|
assert f'{mp.mpf(2.5):.0e}' == '2e+00'
|
|
assert f'{mp.mpf(2.5000001):.0e}' == '3e+00'
|
|
assert f'{mp.mpf(3.499999999999):.0e}' == '3e+00'
|
|
assert f'{mp.mpf(3.5):.0e}' == '4e+00'
|
|
assert f'{mp.mpf(4.5):.0e}' == '4e+00'
|
|
assert f'{mp.mpf(5.5):.0e}' == '6e+00'
|
|
assert f'{mp.mpf(6.5):.0e}' == '6e+00'
|
|
assert f'{mp.mpf(7.5):.0e}' == '8e+00'
|
|
assert f'{mp.mpf(8.5):.0e}' == '8e+00'
|
|
assert f'{mp.mpf(9.4999):.0e}' == '9e+00'
|
|
assert f'{mp.mpf(9.5):.0e}' == '1e+01'
|
|
assert f'{mp.mpf(10.5):.0e}' == '1e+01'
|
|
assert f'{mp.mpf(14.999):.0e}' == '1e+01'
|
|
assert f'{mp.mpf(15):.0e}' == '2e+01'
|
|
|
|
# precision 1
|
|
assert f'{mp.mpf(0.0001):.1e}' == '1.0e-04'
|
|
assert f'{mp.mpf(0.001):.1e}' == '1.0e-03'
|
|
assert f'{mp.mpf(0.01):.1e}' == '1.0e-02'
|
|
assert f'{mp.mpf(0.1):.1e}' == '1.0e-01'
|
|
assert f'{mp.mpf(1):.1e}' == '1.0e+00'
|
|
assert f'{mp.mpf(10):.1e}' == '1.0e+01'
|
|
assert f'{mp.mpf(100):.1e}' == '1.0e+02'
|
|
assert f'{mp.mpf(120):.1e}' == '1.2e+02'
|
|
assert f'{mp.mpf(123):.1e}' == '1.2e+02'
|
|
assert f'{mp.mpf(123.4):.1e}' == '1.2e+02'
|
|
|
|
# precision 2
|
|
assert f'{mp.mpf(0.00013):.2e}' == '1.30e-04'
|
|
assert f'{mp.mpf(0.000135):.2e}' == '1.35e-04'
|
|
assert f'{mp.mpf(0.0001357):.2e}' == '1.36e-04'
|
|
assert f'{mp.mpf(0.0001):.2e}' == '1.00e-04'
|
|
assert f'{mp.mpf(0.001):.2e}' == '1.00e-03'
|
|
assert f'{mp.mpf(0.01):.2e}' == '1.00e-02'
|
|
assert f'{mp.mpf(0.1):.2e}' == '1.00e-01'
|
|
assert f'{mp.mpf(1):.2e}' == '1.00e+00'
|
|
assert f'{mp.mpf(10):.2e}' == '1.00e+01'
|
|
assert f'{mp.mpf(100):.2e}' == '1.00e+02'
|
|
assert f'{mp.mpf(1000):.2e}' == '1.00e+03'
|
|
assert f'{mp.mpf(1500):.2e}' == '1.50e+03'
|
|
assert f'{mp.mpf(1590):.2e}' == '1.59e+03'
|
|
assert f'{mp.mpf(1598):.2e}' == '1.60e+03'
|
|
assert f'{mp.mpf(1598.7):.2e}' == '1.60e+03'
|
|
assert f'{mp.mpf(1598.76):.2e}' == '1.60e+03'
|
|
assert f'{mp.mpf(9999):.2e}' == '1.00e+04'
|
|
|
|
# omitted precision defaults to 6
|
|
assert f'{mp.mpf(0):e}' == '0.000000e+00'
|
|
assert f'{mp.mpf(165):e}' == '1.650000e+02'
|
|
assert f'{mp.mpf(1234567):e}' == '1.234567e+06'
|
|
assert f'{mp.mpf(12345678):e}' == '1.234568e+07'
|
|
assert f'{mp.mpf(1.1):e}' == '1.100000e+00'
|
|
|
|
# alternate form always contains a decimal point. This only makes
|
|
# a difference when precision is 0.
|
|
|
|
assert f'{mp.mpf(0.01):#.0e}' == '1.e-02'
|
|
assert f'{mp.mpf(0.1):#.0e}' == '1.e-01'
|
|
assert f'{mp.mpf(1):#.0e}' == '1.e+00'
|
|
assert f'{mp.mpf(10):#.0e}' == '1.e+01'
|
|
assert f'{mp.mpf(100):#.0e}' == '1.e+02'
|
|
assert f'{mp.mpf(0.012):#.0e}' == '1.e-02'
|
|
assert f'{mp.mpf(0.12):#.0e}' == '1.e-01'
|
|
assert f'{mp.mpf(1.2):#.0e}' == '1.e+00'
|
|
assert f'{mp.mpf(12):#.0e}' == '1.e+01'
|
|
assert f'{mp.mpf(120):#.0e}' == '1.e+02'
|
|
assert f'{mp.mpf(123.456):#.0e}' == '1.e+02'
|
|
assert f'{mp.mpf(0.000123456):#.0e}' == '1.e-04'
|
|
assert f'{mp.mpf(123456000):#.0e}' == '1.e+08'
|
|
assert f'{mp.mpf(0.5):#.0e}' == '5.e-01'
|
|
assert f'{mp.mpf(1.4):#.0e}' == '1.e+00'
|
|
assert f'{mp.mpf(1.5):#.0e}' == '2.e+00'
|
|
assert f'{mp.mpf(1.6):#.0e}' == '2.e+00'
|
|
assert f'{mp.mpf(2.4999999):#.0e}' == '2.e+00'
|
|
assert f'{mp.mpf(2.5):#.0e}' == '2.e+00'
|
|
assert f'{mp.mpf(2.5000001):#.0e}' == '3.e+00'
|
|
assert f'{mp.mpf(3.499999999999):#.0e}' == '3.e+00'
|
|
assert f'{mp.mpf(3.5):#.0e}' == '4.e+00'
|
|
assert f'{mp.mpf(4.5):#.0e}' == '4.e+00'
|
|
assert f'{mp.mpf(5.5):#.0e}' == '6.e+00'
|
|
assert f'{mp.mpf(6.5):#.0e}' == '6.e+00'
|
|
assert f'{mp.mpf(7.5):#.0e}' == '8.e+00'
|
|
assert f'{mp.mpf(8.5):#.0e}' == '8.e+00'
|
|
assert f'{mp.mpf(9.4999):#.0e}' == '9.e+00'
|
|
assert f'{mp.mpf(9.5):#.0e}' == '1.e+01'
|
|
assert f'{mp.mpf(10.5):#.0e}' == '1.e+01'
|
|
assert f'{mp.mpf(14.999):#.0e}' == '1.e+01'
|
|
assert f'{mp.mpf(15):#.0e}' == '2.e+01'
|
|
assert f'{mp.mpf(123.4):#.1e}' == '1.2e+02'
|
|
assert f'{mp.mpf(0.0001357):#.2e}' == '1.36e-04'
|
|
|
|
# 'g' code formatting.
|
|
|
|
# zeros
|
|
assert f'{mp.mpf(0):.0g}' == '0'
|
|
assert f'{mp.mpf(0):.1g}' == '0'
|
|
assert f'{mp.mpf(0):.2g}' == '0'
|
|
assert f'{mp.mpf(0):.3g}' == '0'
|
|
assert f'{mp.mpf(0):.4g}' == '0'
|
|
assert f'{mp.mpf(0):.10g}' == '0'
|
|
assert f'{mp.mpf(0):.50g}' == '0'
|
|
assert f'{mp.mpf(0):.100g}' == '0'
|
|
|
|
# nan, infs
|
|
assert f'{inf:g}' == 'inf'
|
|
assert f'{inf:+g}' == '+inf'
|
|
assert f'{inf:G}' == 'INF'
|
|
assert f'{inf:+G}' == '+INF'
|
|
|
|
assert f'{ninf:g}' == '-inf'
|
|
assert f'{ninf:+g}' == '-inf'
|
|
assert f'{ninf:G}' == '-INF'
|
|
assert f'{ninf:+G}' == '-INF'
|
|
|
|
assert f'{nan:g}' == 'nan'
|
|
assert f'{nan:+g}' == '+nan'
|
|
assert f'{nan:G}' == 'NAN'
|
|
assert f'{nan:+G}' == '+NAN'
|
|
|
|
# precision 0 doesn't make a lot of sense for the 'g' code (what does
|
|
# it mean to have no significant digits?); in practice, it's interpreted
|
|
# as identical to precision 1
|
|
assert f'{mp.mpf(1000):.0g}' == '1e+03'
|
|
assert f'{mp.mpf(100):.0g}' == '1e+02'
|
|
assert f'{mp.mpf(10):.0g}' == '1e+01'
|
|
assert f'{mp.mpf(1):.0g}' == '1'
|
|
assert f'{mp.mpf(0.1):.0g}' == '0.1'
|
|
assert f'{mp.mpf(0.01):.0g}' == '0.01'
|
|
assert f'{mp.mpf(1e-3):.0g}' == '0.001'
|
|
assert f'{mp.mpf(1e-4):.0g}' == '0.0001'
|
|
assert f'{mp.mpf(1e-5):.0g}' == '1e-05'
|
|
assert f'{mp.mpf(1e-6):.0g}' == '1e-06'
|
|
assert f'{mp.mpf(12):.0g}' == '1e+01'
|
|
assert f'{mp.mpf(120):.0g}' == '1e+02'
|
|
assert f'{mp.mpf(1.2):.0g}' == '1'
|
|
assert f'{mp.mpf(0.12):.0g}' == '0.1'
|
|
assert f'{mp.mpf(0.012):.0g}' == '0.01'
|
|
assert f'{mp.mpf(0.0012):.0g}' == '0.001'
|
|
assert f'{mp.mpf(0.00012):.0g}' == '0.0001'
|
|
assert f'{mp.mpf(0.000012):.0g}' == '1e-05'
|
|
assert f'{mp.mpf(0.0000012):.0g}' == '1e-06'
|
|
|
|
# precision 1 identical to precision 0
|
|
assert f'{mp.mpf(1000):.1g}' == '1e+03'
|
|
assert f'{mp.mpf(100):.1g}' == '1e+02'
|
|
assert f'{mp.mpf(10):.1g}' == '1e+01'
|
|
assert f'{mp.mpf(1):.1g}' == '1'
|
|
assert f'{mp.mpf(0.1):.1g}' == '0.1'
|
|
assert f'{mp.mpf(0.01):.1g}' == '0.01'
|
|
assert f'{mp.mpf(1e-3):.1g}' == '0.001'
|
|
assert f'{mp.mpf(1e-4):.1g}' == '0.0001'
|
|
assert f'{mp.mpf(1e-5):.1g}' == '1e-05'
|
|
assert f'{mp.mpf(1e-6):.1g}' == '1e-06'
|
|
assert f'{mp.mpf(12):.1g}' == '1e+01'
|
|
assert f'{mp.mpf(120):.1g}' == '1e+02'
|
|
assert f'{mp.mpf(1.2):.1g}' == '1'
|
|
assert f'{mp.mpf(0.12):.1g}' == '0.1'
|
|
assert f'{mp.mpf(0.012):.1g}' == '0.01'
|
|
assert f'{mp.mpf(0.0012):.1g}' == '0.001'
|
|
assert f'{mp.mpf(0.00012):.1g}' == '0.0001'
|
|
assert f'{mp.mpf(0.000012):.1g}' == '1e-05'
|
|
assert f'{mp.mpf(0.0000012):.1g}' == '1e-06'
|
|
|
|
# precision 2
|
|
assert f'{mp.mpf(1000):.2g}' == '1e+03'
|
|
assert f'{mp.mpf(100):.2g}' == '1e+02'
|
|
assert f'{mp.mpf(10):.2g}' == '10'
|
|
assert f'{mp.mpf(1):.2g}' == '1'
|
|
assert f'{mp.mpf(0.1):.2g}' == '0.1'
|
|
assert f'{mp.mpf(0.01):.2g}' == '0.01'
|
|
assert f'{mp.mpf(0.001):.2g}' == '0.001'
|
|
assert f'{mp.mpf(1e-4):.2g}' == '0.0001'
|
|
assert f'{mp.mpf(1e-5):.2g}' == '1e-05'
|
|
assert f'{mp.mpf(1e-6):.2g}' == '1e-06'
|
|
assert f'{mp.mpf(1234):.2g}' == '1.2e+03'
|
|
assert f'{mp.mpf(123):.2g}' == '1.2e+02'
|
|
assert f'{mp.mpf(12.3):.2g}' == '12'
|
|
assert f'{mp.mpf(1.23):.2g}' == '1.2'
|
|
assert f'{mp.mpf(0.123):.2g}' == '0.12'
|
|
assert f'{mp.mpf(0.0123):.2g}' == '0.012'
|
|
assert f'{mp.mpf(0.00123):.2g}' == '0.0012'
|
|
assert f'{mp.mpf(0.000123):.2g}' == '0.00012'
|
|
assert f'{mp.mpf(0.0000123):.2g}' == '1.2e-05'
|
|
|
|
# bad cases from http://bugs.python.org/issue9980
|
|
assert f'{mp.mpf(38210.0):.12g}' == '38210'
|
|
assert f'{mp.mpf(37210.0):.12g}' == '37210'
|
|
assert f'{mp.mpf(36210.0):.12g}' == '36210'
|
|
|
|
# alternate g formatting: always include decimal point and
|
|
# exactly <precision> significant digits.
|
|
assert f'{mp.mpf(0):#.0g}' == '0.'
|
|
assert f'{mp.mpf(0):#.1g}' == '0.'
|
|
assert f'{mp.mpf(0):#.2g}' == '0.0'
|
|
assert f'{mp.mpf(0):#.3g}' == '0.00'
|
|
assert f'{mp.mpf(0):#.4g}' == '0.000'
|
|
|
|
assert f'{mp.mpf(0.2):#.0g}' == '0.2'
|
|
assert f'{mp.mpf(0.2):#.1g}' == '0.2'
|
|
assert f'{mp.mpf(0.2):#.2g}' == '0.20'
|
|
assert f'{mp.mpf(0.2):#.3g}' == '0.200'
|
|
assert f'{mp.mpf(0.2):#.4g}' == '0.2000'
|
|
assert f'{mp.mpf(0.2):#.10g}' == '0.2000000000'
|
|
|
|
assert f'{mp.mpf(2):#.0g}' == '2.'
|
|
assert f'{mp.mpf(2):#.1g}' == '2.'
|
|
assert f'{mp.mpf(2):#.2g}' == '2.0'
|
|
assert f'{mp.mpf(2):#.3g}' == '2.00'
|
|
assert f'{mp.mpf(2):#.4g}' == '2.000'
|
|
|
|
assert f'{mp.mpf(20):#.0g}' == '2.e+01'
|
|
assert f'{mp.mpf(20):#.1g}' == '2.e+01'
|
|
assert f'{mp.mpf(20):#.2g}' == '20.'
|
|
assert f'{mp.mpf(20):#.3g}' == '20.0'
|
|
assert f'{mp.mpf(20):#.4g}' == '20.00'
|
|
|
|
assert f'{mp.mpf(234.56):#.0g}' == '2.e+02'
|
|
assert f'{mp.mpf(234.56):#.1g}' == '2.e+02'
|
|
assert f'{mp.mpf(234.56):#.2g}' == '2.3e+02'
|
|
assert f'{mp.mpf(234.56):#.3g}' == '235.'
|
|
assert f'{mp.mpf(234.56):#.4g}' == '234.6'
|
|
assert f'{mp.mpf(234.56):#.5g}' == '234.56'
|
|
assert f'{mp.mpf(234.56):#.6g}' == '234.560'
|
|
|
|
|
|
def test_mpf_float():
|
|
'''
|
|
These are additional random tests that check that mp.mpf and fp.mpf yield
|
|
the same results for default precision.
|
|
'''
|
|
|
|
for _ in range(10000):
|
|
fmt_str = random_fmt()
|
|
num = random.choice(
|
|
(
|
|
random.uniform(-1e300, 1e300),
|
|
random.uniform(-1e-300, 1e-300)
|
|
)
|
|
)
|
|
|
|
assert fmt_str.format(fp.mpf(num)) == fmt_str.format(mp.mpf(num))
|
|
|
|
# These additional tests test for mpf initialized form subnormal floats
|
|
for _ in range(10000):
|
|
fmt_str = random_fmt()
|
|
num = fp.mpf('{:.15f}e{:d}'.format(
|
|
random.uniform(1, 10), random.randint(-324, -308)))
|
|
|
|
# We skip the case when num == 0 since mpmath does not have negative
|
|
# zero.
|
|
if num != 0 and random.randint(0, 1):
|
|
num = -num
|
|
assert fmt_str.format(num) == fmt_str.format(mp.mpf(num))
|
|
|
|
# Test the same random formats with special numbers
|
|
for num in (inf, -inf, nan, 0):
|
|
fmt_str = random_fmt()
|
|
assert fmt_str.format(fp.mpf(num)) == fmt_str.format(mp.mpf(num))
|
|
|
|
|
|
def test_mpf_fmt():
|
|
'''
|
|
These tests are either specific tests to mpf, or tests that cover
|
|
code that is not covered in the CPython tests.
|
|
'''
|
|
|
|
with workdps(1000):
|
|
# Numbers with more than 15 significant digits
|
|
# fixed format
|
|
assert f"{mp.mpf('1.234567890123456789'):.20f}" == '1.23456789012345678900'
|
|
assert f"{mp.mpf('1.234567890123456789'):.25f}" == '1.2345678901234567890000000'
|
|
assert f"{mp.mpf('1.234567890123456789'):.30f}" == '1.234567890123456789000000000000'
|
|
assert f"{mp.mpf('1e-50'):.50f}" == '0.00000000000000000000000000000000000000000000000001'
|
|
|
|
# scientific notation
|
|
assert f"{mp.mpf('1.234567890123456789'):.20e}" == '1.23456789012345678900e+00'
|
|
assert f"{mp.mpf('1.234567890123456789'):.25e}" == '1.2345678901234567890000000e+00'
|
|
assert f"{mp.mpf('1.234567890123456789'):.30e}" == '1.234567890123456789000000000000e+00'
|
|
assert f"{mp.mpf('1e-50'):.50e}" == '1.00000000000000000000000000000000000000000000000000e-50'
|
|
|
|
# width and fill char
|
|
assert f"{mp.mpf('0.01'):z<10.5f}" == '0.01000zzz'
|
|
assert f"{mp.mpf('0.01'):z^10.5f}" == 'z0.01000zz'
|
|
assert f"{mp.mpf('0.01'):z>10.5f}" == 'zzz0.01000'
|
|
assert f"{mp.mpf('0.01'):z=10.5f}" == 'zzz0.01000'
|
|
|
|
assert f"{mp.mpf('0.01'):z<+10.5f}" == '+0.01000zz'
|
|
assert f"{mp.mpf('0.01'):z^+10.5f}" == 'z+0.01000z'
|
|
assert f"{mp.mpf('0.01'):z>+10.5f}" == 'zz+0.01000'
|
|
assert f"{mp.mpf('0.01'):z=+10.5f}" == '+zz0.01000'
|
|
|
|
assert f"{mp.mpf('-0.01'):z<10.5f}" == '-0.01000zz'
|
|
assert f"{mp.mpf('-0.01'):z^10.5f}" == 'z-0.01000z'
|
|
assert f"{mp.mpf('-0.01'):z>10.5f}" == 'zz-0.01000'
|
|
assert f"{mp.mpf('-0.01'):z=10.5f}" == '-zz0.01000'
|
|
|
|
assert f"{mp.mpf('0.01'):z<15.5e}" == '1.00000e-02zzzz'
|
|
assert f"{mp.mpf('0.01'):z^15.5e}" == 'zz1.00000e-02zz'
|
|
assert f"{mp.mpf('0.01'):z>15.5e}" == 'zzzz1.00000e-02'
|
|
assert f"{mp.mpf('0.01'):z=15.5e}" == 'zzzz1.00000e-02'
|
|
|
|
assert f"{mp.mpf('0.01'):z<+15.5e}" == '+1.00000e-02zzz'
|
|
assert f"{mp.mpf('0.01'):z^+15.5e}" == 'z+1.00000e-02zz'
|
|
assert f"{mp.mpf('0.01'):z>+15.5e}" == 'zzz+1.00000e-02'
|
|
assert f"{mp.mpf('0.01'):z=+15.5e}" == '+zzz1.00000e-02'
|
|
|
|
assert f"{mp.mpf('-0.01'):z<15.5e}" == '-1.00000e-02zzz'
|
|
assert f"{mp.mpf('-0.01'):z^15.5e}" == 'z-1.00000e-02zz'
|
|
assert f"{mp.mpf('-0.01'):z>15.5e}" == 'zzz-1.00000e-02'
|
|
assert f"{mp.mpf('-0.01'):z=15.5e}" == '-zzz1.00000e-02'
|
|
|
|
# capitalized scientific notation
|
|
assert f"{mp.mpf('-0.01'):z<15.5E}" == '-1.00000E-02zzz'
|
|
|
|
# generalized format
|
|
assert f"{mp.mpf('1.234567890123456789'):.20g}" == '1.234567890123456789'
|
|
assert f"{mp.mpf('1.234567890123456789'):.25g}" == '1.234567890123456789'
|
|
assert f"{mp.mpf('1.234567890123456789'):.30g}" == '1.234567890123456789'
|
|
assert f"{mp.mpf('1e-50'):.50g}" == '1e-50'
|
|
assert f"{mp.mpf('1e-50'):.50G}" == '1E-50'
|
|
|
|
assert f"{mp.mpf('1e-50'):}" == '1e-50'
|
|
|
|
# thousands separator
|
|
assert f"{mp.mpf('1e9'):,.0f}" == '1,000,000,000'
|
|
assert f"{mp.mpf('123456789.0123456'):,.4f}" == '123,456,789.0123'
|
|
assert f"{mp.mpf('1234567890.123456'):_.4f}" == '1_234_567_890.1235'
|
|
assert f"{mp.mpf('1234.5678'):_.4f}" == '1_234.5678'
|
|
|
|
assert f"{mp.mpf('1e9'):,.0e}" == '1e+09'
|
|
assert f"{mp.mpf('123456789.0123456'):,.4e}" == '1.2346e+08'
|
|
assert f"{mp.mpf('1234567890.123456'):_.4e}" == '1.2346e+09'
|
|
assert f"{mp.mpf('1234.5678'):_.4e}" == '1.2346e+03'
|
|
|
|
# Tests for no_neg_0
|
|
assert f"{mp.mpf('-1e-4'):,.2f}" == '-0.00'
|
|
assert f"{mp.mpf('-1e-4'):z,.2f}" == '0.00'
|
|
|
|
# Tests for = alignment
|
|
assert f"{mp.mpf('0.24'):=+20.2f}" == '+ 0.24'
|
|
assert f"{mp.mpf('0.24'):=+020.2e}" == '+000000000002.40e-01'
|
|
assert f"{mp.mpf('0.24'):=+020.2g}" == '+0000000000000000.24'
|
|
|
|
# Tests for different kinds of rounding
|
|
num = mp.mpf('-1.23456789999901234567')
|
|
assert f"{num:=.2Uf}" == "-1.23"
|
|
assert f"{num:=.2Df}" == "-1.24"
|
|
assert f"{num:=.2Zf}" == "-1.23"
|
|
assert f"{num:=.2Nf}" == "-1.23"
|
|
assert f"{num:=.2Yf}" == "-1.24"
|
|
|
|
assert f"{num:=.3Uf}" == "-1.234"
|
|
assert f"{num:=.3Df}" == "-1.235"
|
|
assert f"{num:=.3Zf}" == "-1.234"
|
|
assert f"{num:=.3Nf}" == "-1.235"
|
|
assert f"{num:=.3Yf}" == "-1.235"
|
|
|
|
assert f"{num:=.10Uf}" == "-1.2345678999"
|
|
assert f"{num:=.10Df}" == "-1.2345679000"
|
|
assert f"{num:=.10Zf}" == "-1.2345678999"
|
|
assert f"{num:=.10Nf}" == "-1.2345679000"
|
|
assert f"{num:=.10Yf}" == "-1.2345679000"
|
|
|
|
num = mp.mpf('1.23456789999901234567')
|
|
assert f"{num:=.2Uf}" == "1.24"
|
|
assert f"{num:=.2Df}" == "1.23"
|
|
assert f"{num:=.2Zf}" == "1.23"
|
|
assert f"{num:=.2Nf}" == "1.23"
|
|
assert f"{num:=.2Yf}" == "1.24"
|
|
|
|
assert f"{num:=.3Uf}" == "1.235"
|
|
assert f"{num:=.3Df}" == "1.234"
|
|
assert f"{num:=.3Zf}" == "1.234"
|
|
assert f"{num:=.3Nf}" == "1.235"
|
|
assert f"{num:=.3Yf}" == "1.235"
|
|
|
|
assert f"{num:=.10Uf}" == "1.2345679000"
|
|
assert f"{num:=.10Df}" == "1.2345678999"
|
|
assert f"{num:=.10Zf}" == "1.2345678999"
|
|
assert f"{num:=.10Nf}" == "1.2345679000"
|
|
assert f"{num:=.10Yf}" == "1.2345679000"
|
|
|
|
num = mp.mpf('-123.456789999901234567')
|
|
assert f"{num:=.2Ue}" == "-1.23e+02"
|
|
assert f"{num:=.2De}" == "-1.24e+02"
|
|
assert f"{num:=.2Ze}" == "-1.23e+02"
|
|
assert f"{num:=.2Ne}" == "-1.23e+02"
|
|
assert f"{num:=.2Ye}" == "-1.24e+02"
|
|
|
|
assert f"{num:=.3Ue}" == "-1.234e+02"
|
|
assert f"{num:=.3De}" == "-1.235e+02"
|
|
assert f"{num:=.3Ze}" == "-1.234e+02"
|
|
assert f"{num:=.3Ne}" == "-1.235e+02"
|
|
assert f"{num:=.3Ye}" == "-1.235e+02"
|
|
|
|
assert f"{num:=.10Ue}" == "-1.2345678999e+02"
|
|
assert f"{num:=.10De}" == "-1.2345679000e+02"
|
|
assert f"{num:=.10Ze}" == "-1.2345678999e+02"
|
|
assert f"{num:=.10Ne}" == "-1.2345679000e+02"
|
|
assert f"{num:=.10Ye}" == "-1.2345679000e+02"
|
|
|
|
num = mp.mpf('123456.789999901234567')
|
|
assert f"{num:=.2Ue}" == "1.24e+05"
|
|
assert f"{num:=.2De}" == "1.23e+05"
|
|
assert f"{num:=.2Ze}" == "1.23e+05"
|
|
assert f"{num:=.2Ne}" == "1.23e+05"
|
|
assert f"{num:=.2Ye}" == "1.24e+05"
|
|
|
|
assert f"{num:=.3Ue}" == "1.235e+05"
|
|
assert f"{num:=.3De}" == "1.234e+05"
|
|
assert f"{num:=.3Ze}" == "1.234e+05"
|
|
assert f"{num:=.3Ne}" == "1.235e+05"
|
|
assert f"{num:=.3Ye}" == "1.235e+05"
|
|
|
|
assert f"{num:=.10Ue}" == "1.2345679000e+05"
|
|
assert f"{num:=.10De}" == "1.2345678999e+05"
|
|
assert f"{num:=.10Ze}" == "1.2345678999e+05"
|
|
assert f"{num:=.10Ne}" == "1.2345679000e+05"
|
|
assert f"{num:=.10Ye}" == "1.2345679000e+05"
|
|
|
|
assert f"{mp.mpf('123.456'):.2Ug}" == "1.3e+02"
|
|
assert f"{mp.mpf('123.456'):.2Dg}" == "1.2e+02"
|
|
assert f"{mp.mpf('123.456'):.2Zg}" == "1.2e+02"
|
|
assert f"{mp.mpf('123.456'):.2Ng}" == "1.2e+02"
|
|
assert f"{mp.mpf('123.456'):.2Yg}" == "1.3e+02"
|
|
|
|
assert f"{mp.mpf('-123.456'):.2Ug}" == "-1.2e+02"
|
|
assert f"{mp.mpf('-123.456'):.2Dg}" == "-1.3e+02"
|
|
assert f"{mp.mpf('-123.456'):.2Zg}" == "-1.2e+02"
|
|
assert f"{mp.mpf('-123.456'):.2Ng}" == "-1.2e+02"
|
|
assert f"{mp.mpf('-123.456'):.2Yg}" == "-1.3e+02"
|
|
|
|
assert f"{mp.mpf('123.456'):.5Ug}" == "123.46"
|
|
assert f"{mp.mpf('123.456'):.5Dg}" == "123.45"
|
|
assert f"{mp.mpf('123.456'):.5Zg}" == "123.45"
|
|
assert f"{mp.mpf('123.456'):.5Ng}" == "123.46"
|
|
assert f"{mp.mpf('123.456'):.5Yg}" == "123.46"
|
|
|
|
assert f"{mp.mpf('-123.456'):.5Ug}" == "-123.45"
|
|
assert f"{mp.mpf('-123.456'):.5Dg}" == "-123.46"
|
|
assert f"{mp.mpf('-123.456'):.5Zg}" == "-123.45"
|
|
assert f"{mp.mpf('-123.456'):.5Ng}" == "-123.46"
|
|
assert f"{mp.mpf('-123.456'):.5Yg}" == "-123.46"
|
|
|
|
# Special cases were tying is relevant (cases involve exact floats)
|
|
assert f"{mp.mpf('0.25'):.1Nf}" == "0.2"
|
|
assert f"{mp.mpf('0.75'):.1Nf}" == "0.8"
|
|
|
|
num = mp.mpf('0.1')
|
|
assert f"{-num:=.2Df}" == "-0.11"
|
|
assert f"{-num:=.3Df}" == "-0.101"
|
|
assert f"{-num:=.4Df}" == "-0.1001"
|
|
assert f"{-num:=.5Df}" == "-0.10001"
|
|
assert f"{-num:=.6Df}" == "-0.100001"
|
|
assert f"{-num:=.7Df}" == "-0.1000001"
|
|
|
|
assert f"{-num:=.2De}" == "-1.01e-01"
|
|
assert f"{-num:=.3De}" == "-1.001e-01"
|
|
assert f"{-num:=.4De}" == "-1.0001e-01"
|
|
assert f"{-num:=.5De}" == "-1.00001e-01"
|
|
assert f"{-num:=.6De}" == "-1.000001e-01"
|
|
assert f"{-num:=.7De}" == "-1.0000001e-01"
|
|
|
|
assert f"{num:=.2Uf}" == "0.11"
|
|
assert f"{num:=.3Uf}" == "0.101"
|
|
assert f"{num:=.4Uf}" == "0.1001"
|
|
assert f"{num:=.5Uf}" == "0.10001"
|
|
assert f"{num:=.6Uf}" == "0.100001"
|
|
assert f"{num:=.7Uf}" == "0.1000001"
|
|
|
|
assert f"{num:=.2Ue}" == "1.01e-01"
|
|
assert f"{num:=.3Ue}" == "1.001e-01"
|
|
assert f"{num:=.4Ue}" == "1.0001e-01"
|
|
assert f"{num:=.5Ue}" == "1.00001e-01"
|
|
assert f"{num:=.6Ue}" == "1.000001e-01"
|
|
assert f"{num:=.7Ue}" == "1.0000001e-01"
|
|
|
|
num = mp.mpf('0.25')
|
|
assert f"{-num:=.2Df}" == "-0.25"
|
|
assert f"{-num:=.3Df}" == "-0.250"
|
|
assert f"{-num:=.4Df}" == "-0.2500"
|
|
assert f"{-num:=.5Df}" == "-0.25000"
|
|
assert f"{-num:=.6Df}" == "-0.250000"
|
|
assert f"{-num:=.7Df}" == "-0.2500000"
|
|
|
|
assert f"{-num:=.2De}" == "-2.50e-01"
|
|
assert f"{-num:=.3De}" == "-2.500e-01"
|
|
assert f"{-num:=.4De}" == "-2.5000e-01"
|
|
assert f"{-num:=.5De}" == "-2.50000e-01"
|
|
assert f"{-num:=.6De}" == "-2.500000e-01"
|
|
assert f"{-num:=.7De}" == "-2.5000000e-01"
|
|
|
|
assert f"{num:=.2Uf}" == "0.25"
|
|
assert f"{num:=.3Uf}" == "0.250"
|
|
assert f"{num:=.4Uf}" == "0.2500"
|
|
assert f"{num:=.5Uf}" == "0.25000"
|
|
assert f"{num:=.6Uf}" == "0.250000"
|
|
assert f"{num:=.7Uf}" == "0.2500000"
|
|
|
|
assert f"{num:=.2Ue}" == "2.50e-01"
|
|
assert f"{num:=.3Ue}" == "2.500e-01"
|
|
assert f"{num:=.4Ue}" == "2.5000e-01"
|
|
assert f"{num:=.5Ue}" == "2.50000e-01"
|
|
assert f"{num:=.6Ue}" == "2.500000e-01"
|
|
assert f"{num:=.7Ue}" == "2.5000000e-01"
|
|
|
|
# Changing the work precision changes the number printed (This is
|
|
# expected behavior)
|
|
with mp.workdps(20):
|
|
assert f"{mp.mpf('0.1'):=.4Uf}" == "0.1000"
|
|
assert f"{mp.mpf('-0.1'):=.4Df}" == "-0.1000"
|
|
|
|
|
|
def test_errors():
|
|
with pytest.raises(ValueError):
|
|
# wrong format type
|
|
f"{mp.mpf('-4'):22.15k}"
|
|
|
|
with pytest.raises(ValueError, match="Invalid format specifier '<z15.e'"):
|
|
# no precision specified after .
|
|
f"{mp.mpf('-0.01'):<z15.e}"
|
|
|
|
with pytest.raises(ValueError, match="Invalid format specifier '10.5fk'"):
|
|
f"{mp.mpf('4'):10.5fk}"
|
|
|
|
with pytest.raises(ValueError, match="Invalid format specifier '12.3 E '"):
|
|
f"{mp.mpf('4'):12.3 E }"
|
|
|
|
with pytest.raises(ValueError, match="Cannot specify both 0-padding "
|
|
"and a fill character"):
|
|
f"{mp.mpf('4'):q<03f}"
|