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
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')