Is floating point arbitrary precision available?

后端 未结 5 1309
梦毁少年i
梦毁少年i 2020-11-22 09:11

Just for fun and because it was really easy, I\'ve written a short program to generate Grafting numbers, but because of floating point precision issues it\'s not finding som

相关标签:
5条回答
  • 2020-11-22 09:12

    For this particular problem, decimal is a great way to go, because it stores the decimal digits as tuples!

    >>> a = decimal.Decimal(9999999998)
    >>> a.as_tuple()
    DecimalTuple(sign=0, digits=(9, 9, 9, 9, 9, 9, 9, 9, 9, 8), exponent=0)
    

    Since you're looking for a property that is most naturally expressed in decimal notation, it's a bit silly to use a binary representation. The wikipedia page you linked to didn't indicate how many "non-grafting digits" may appear before the "grafting digits" begin, so this lets you specify:

    >>> def isGrafting(dec, max_offset=5):
    ...     dec_digits = dec.as_tuple().digits
    ...     sqrt_digits = dec.sqrt().as_tuple().digits
    ...     windows = [sqrt_digits[o:o + len(dec_digits)] for o in range(max_offset)]
    ...     return dec_digits in windows
    ... 
    >>> isGrafting(decimal.Decimal(9999999998))
    True
    >>> isGrafting(decimal.Decimal(77))
    True
    

    I think there's a good chance the result of Decimal.sqrt() will be more accurate, at least for this, than the result of math.sqrt() because of the conversion between binary representation and decimal representation. Consider the following, for example:

    >>> num = decimal.Decimal(1) / decimal.Decimal(7)
    >>> decimal.Decimal(math.sqrt(num) ** 2) * 7
    Decimal('0.9999999999999997501998194593')
    >>> decimal.Decimal(num.sqrt() ** 2) * 7
    Decimal('1.000000000000000000000000000')
    
    0 讨论(0)
  • 2020-11-22 09:17

    Python has no built-in arbitrary-precision floats, but there are 3rd-party Python packages that use GMP: gmpy and PyGMP.

    0 讨论(0)
  • 2020-11-22 09:20

    You can try with Decimal instead of floatingpoint.

    0 讨论(0)
  • 2020-11-22 09:25

    In the standard library, the decimal module may be what you're looking for. Also, I have found mpmath to be quite helpful. The documentation has many great examples as well (unfortunately my office computer does not have mpmath installed; otherwise I would verify a few examples and post them).

    One caveat about the decimal module, though. The module contains several in-built functions for simple mathematical operations (e.g. sqrt), but the results from these functions may not always match the corresponding function in math or other modules at higher precisions (although they may be more accurate). For example,

    from decimal import *
    import math
    
    getcontext().prec = 30
    num = Decimal(1) / Decimal(7)
    
    print("   math.sqrt: {0}".format(Decimal(math.sqrt(num))))
    print("decimal.sqrt: {0}".format(num.sqrt()))
    

    In Python 3.2.3, this outputs the first two lines

       math.sqrt: 0.37796447300922719758631274089566431939601898193359375
    decimal.sqrt: 0.377964473009227227214516536234
    actual value: 0.3779644730092272272145165362341800608157513118689214
    

    which as stated, isn't exactly what you would expect, and you can see that the higher the precision, the less the results match. Note that the decimal module does have more accuracy in this example, since it more closely matches the actual value.

    0 讨论(0)
  • 2020-11-22 09:27

    use decimal, (here is a clearer example):

    >>> 2.3-2.2
    0.09999999999999964
    >>> from decimal import Decimal
    >>> Decimal('2.3')-Decimal('2.2')
    Decimal('0.1')
    >>> float(Decimal('2.3')-Decimal('2.2'))
    0.1
    >>> 
    
    0 讨论(0)
提交回复
热议问题