Solo por diversión y porque era realmente fácil, he escrito un programa corto para generar Grafting numbers, pero debido a problemas de precisión de punto flotante no está encontrando algunos de los ejemplos más grandes.¿Precisión arbitraria de punto flotante de Python disponible?
def isGrafting(a):
for i in xrange(1, int(ceil(log10(a))) + 2):
if a == floor((sqrt(a) * 10**(i-1)) % 10**int(ceil(log10(a)))):
return 1
a = 0
while(1):
if (isGrafting(a)):
print "%d %.15f" % (a, sqrt(a))
a += 1
Este código pierde al menos un número de injerto conocido. 9999999998 => 99999.99998999999999949999999994999999999374999999912...
Parece perder precisión adicional después de multiplicar por 10**5
.
>>> a = 9999999998
>>> sqrt(a)
99999.99999
>>> a == floor((sqrt(a) * 10**(5)) % 10**int(ceil(log10(a))))
False
>>> floor((sqrt(a) * 10**(5)) % 10**int(ceil(log10(a))))
9999999999.0
>>> print "%.15f" % sqrt(a)
99999.999989999996615
>>> print "%.15f" % (sqrt(a) * 10**5)
9999999999.000000000000000
Así que escribió un pequeño programa C++ para ver si era mi CPU truncar el número de coma flotante o pitón de alguna manera.
#include <cstdio>
#include <cmath>
#include <stdint.h>
int main()
{
uint64_t a = 9999999998;
printf("%ld %.15f %.15f %.15f %.15f\n", a, sqrt((double)a), sqrt((double)a)*1e4, sqrt((double)a)*1e5, sqrt((double)a)*1e6);
a = 999999999998;
printf("%ld %.15f %.15f %.15f %.15f\n", a, sqrt((double)a), sqrt((double)a)*1e5, sqrt((double)a)*1e6, sqrt((double)a)*1e7);
a = 99999999999998;
printf("%ld %.15f %.15f %.15f %.15f\n", a, sqrt((double)a), sqrt((double)a)*1e6, sqrt((double)a)*1e7, sqrt((double)a)*1e8);
return 0;
}
que da salida:
9999999998 99999.999989999996615 999999999.899999976158142 9999999999.000000000000000 99999999990.000000000000000
999999999998 999999.999998999992386 99999999999.899993896484375 999999999999.000000000000000 9999999999990.000000000000000
99999999999998 9999999.999999899417162 9999999999999.900390625000000 99999999999999.000000000000000 999999999999990.000000000000000
para que parezca que estoy corriendo con fuerza contra los límites de precisión de punto flotante y la CPU está cortando el resto de bits, ya que piensa que la diferencia restante es un error de coma flotante ¿Hay alguna forma de solucionar esto bajo Python? ¿O necesito pasar a C y usar GMP o algo?
para llevar a cabo la aritmética exacta en números racionales, [ 'fractions' módulo] (https://docs.python.org/3/library/fractions.html) podrían utilizarse . – jfs