You are on page 1of 5

5/1/2017 14.AritmticadePuntoFlotante:ProblemasyLimitacionesTutorialdePythonv2.7.

14. Aritmtica de Punto Flotante: Problemas y


Limitaciones
Losnmerosdepuntoflotanteserepresentanenelhardwaredelacomputadoraenfraccionesen
base2(binario).Porejemplo,lafraccindecimal

0.125

...tieneelvalor1/10+2/100+5/1000,ydelamismamaneralafraccinbinaria

0.001

...tieneelvalor0/2+0/4+1/8.Estasdosfraccionestienenvaloresidnticos,lanicadiferencia
realesquelaprimeraestescritaennotacinfraccionalenbase10ylasegundaenbase2.

Desafortunadamente, la mayora de las fracciones decimales no pueden representarse


exactamente como fracciones binarias. Como consecuencia, en general los nmeros de punto
flotantedecimalqueingressenlacomputadorasonsloaproximadosporlosnmerosdepunto
flotantebinarioquerealmenteseguardanenlamquina.

El problema es ms fcil de entender primero en base 10. Consider la fraccin 1/3. Pods
aproximarlacomounafraccindebase10

0.3

...o,mejor,

0.33

...o,mejor,

0.333

...yas.Noimportacuantosdgitosdeseesescribir,elresultadonuncaserexactamente1/3,pero
serunaaproximacincadavezmejorde1/3.

Delamismamanera,noimportacuantosdgitosenbase2quierasusar,elvalordecimal0.1no
puederepresentarseexactamentecomounafraccinenbase2.Enbase2,1/10eslasiguiente
fraccinqueserepiteinfinitamente:

0.0001100110011001100110011001100110011001100110011...

Frenencualquiernmerofinitodebits,ytendrsunaaproximacin.Esporestoquevescosas
como:

>>>0.1
0.10000000000000001

http://docs.python.org.ar/tutorial/2/floatingpoint.html 1/5
5/1/2017 14.AritmticadePuntoFlotante:ProblemasyLimitacionesTutorialdePythonv2.7.0

Enlamayoradelasmquinasdehoyenda,esoesloqueverssiingress0.1enunpromptde
Python. Quizs no, sin embargo, porque la cantidad de bits usados por el hardware para
almacenar valores de punto flotante puede variar en las distintas mquinas, y Python slo
muestraunaaproximacindelvalordecimalverdaderodelaaproximacinbinariaguardadaporla
mquina.Enlamayoradelasmquinas,siPythonfueraamostrarelverdaderovalordecimalde
laaproximacinalmacenadapor0.1,tendraquemostrarsinembargo

>>>0.1
0.1000000000000000055511151231257827021181583404541015625

El prompt de Python usa la funcin integrada repr() para obtener una versin en cadena de
caracteres de todo lo que muestra. Para flotantes, repr(float) redondea el valor decimal
verdaderoa17dgitossignificativos,dando

0.10000000000000001

repr(float)
produce 17 dgitos significativos porque esto es suficiente (en la mayora de las
mquinas)paraquesecumpla eval(repr(x))==x exactamenteparatodoslosflotantesfinitosX,
peroredondeandoa16dgitosnoessuficienteparaqueseaverdadero.

Notqueestaeslaverdaderanaturalezadelpuntoflotantebinario:noesunerrordePython,y
tampoco es un error en tu cdigo. Vers lo mismo en todos los lenguajes que soportan la
aritmticadepuntoflotantedetuhardware(apesardequeenalgunoslenguajesporomisinno
muestrenladiferencia,onolohaganentodoslosmodosdesalida).

Lafuncinintegrada:func:strde Pythonproduce slo 12 dgitos significativos, y quizs quieras


usaresa.Normalmente eval(str(x)) noreproducirx,perolasalidaquizsseamsplacenterade
ver:

>>>printstr(0.1)
0.1

Esimportantedarsecuentadequeestoes,realmente,unailusin:elvalorenlamquinanoes
exactamente1/10,simplementeestsredondeandoelvalorquesemuestra del valor verdadero
delamquina.

Aestasesiguenotrassorpresas.Porejemplo,luegodever:

>>>0.1
0.10000000000000001

...quizs ests tentado de usar la funcin round() para recortar el resultado al dgito que
esperabas.Peroeslomismo:

>>>round(0.1,1)
0.10000000000000001

El problema es que el valor de punto flotante binario almacenado para 0.1 ya era la mejor
aproximacinbinariaposiblede1/10,demaneraqueintentarredondearlanuevamentenopuede
mejorarla:yaeralamejorposible.
http://docs.python.org.ar/tutorial/2/floatingpoint.html 2/5
5/1/2017 14.AritmticadePuntoFlotante:ProblemasyLimitacionesTutorialdePythonv2.7.0

Otraconsecuencia es que como 0.1 no es exactamente 1/10, sumar diezvaloresde0.1quizs


tampocodexactamente1.0:

>>>suma=0.0
>>>foriinrange(10):
...suma+=0.1
...
>>>suma
0.9999999999999999

Laaritmticadepuntoflotantebinariatienevariassorpresascomoesta.Elproblemacon0.1es
explicadocondetalleabajo,enlaseccinErrordeRepresentacin.MirlosPeligrosdelPunto
Flotante (en ingls, The Perils of Floating Point) para una ms completa recopilacin de otras
sorpresasnormales.

Comodicecercadelfinal,nohayrespuestasfciles.Apesardeeso,noletengasmuchomiedo
alpuntoflotante!LoserroresenlasoperacionesflotantesdePythonseheredandelhardwarede
puntoflotante,yenlamayoradelasmquinasestnenelordendenomsdeuna1parteen
2**53 por operacin. Eso es ms que adecuado para la mayora de las tareas, pero necesits
tener en cuenta que no es aritmtica decimal, y que cada operacin de punto flotante sufre un
nuevoerrorderedondeo.

Apesardequeexistencasospatolgicos,paralamayoradeusoscasualesdelaaritmticade
puntoflotantealfinalverselresultadoqueesperssisimplementeredondesloquemostrsde
tus resultados finales al nmero de dgitos decimales que espers. str() es normalmente
suficiente,yparauncontrolmsfinomirlosparmetrosdelmtododeformateo str.format() en
formatstrings.

14.1. Error de Representacin


Estaseccinexplicaelejemplo0.1endetalle,ymuestracomoenlamayoradeloscasosvos
mismo pods realizar un anlisis exacto como este. Se asume un conocimiento bsico de la
representacindepuntoflotantebinario.

Error de representacin se refiere al hecho de que algunas (la mayora) de las fracciones
decimalesnopuedenrepresentarseexactamentecomofraccionesbinarias(enbase2).Estaesla
raznprincipaldeporquPython(oPerl,C,C++,Java,Fortran,ytantosotros)frecuentemente
nomostrarnelnmerodecimalexactoqueespers:

>>>0.1
0.10000000000000001

Porqueseso?1/10 no es representable exactamente como una fraccin binaria. Casi todas


lasmquinasdehoyenda(Noviembredel2000)usanaritmticadepuntoflotanteIEEE754,y
casitodaslasplataformasmapeanlosflotantesdePythonaldobleprecisindeIEEE754.Estos
doblestienen53bitsdeprecisin,porlotantoenlaentradalacomputadoraintentaconvertir0.1
a la fraccin ms cercana que puede de la forma J/2***N* donde J es un entero que contiene
exactamente53bits.Reescribiendo

1/10~=J/(2**N)

http://docs.python.org.ar/tutorial/2/floatingpoint.html 3/5
5/1/2017 14.AritmticadePuntoFlotante:ProblemasyLimitacionesTutorialdePythonv2.7.0

...como

J~=2**N/10

...yrecordandoqueJtieneexactamente53bits(es >=2**52 pero <2**53 ),elmejorvalorparaN


es56:

>>>2**52
4503599627370496L
>>>2**53
9007199254740992L
>>>2**56/10
7205759403792793L

Osea,56eselnicovalorparaNquedejaJconexactamente53bits.Elmejorvalorposiblepara
Jesentonceselcocienteredondeado:

>>>q,r=divmod(2**56,10)
>>>r
6L

Yaqueelrestoesmsquelamitadde10,lamejoraproximacinseobtieneredondendolo:

>>>q+1
7205759403792794L

Porlotantolamejoraproximacina1/10endobleprecisin754esesosobre2**56,o

7205759403792794/72057594037927936

Not que como lo redondeamos, esto es un poquito ms grande que 1/10 si no lo hubiramos
redondeado,elcocientehubiesesidounpoquitomenorque1/10.Peronohaycasoenquesea
exactamente1/10!

Entonces la computadora nunca ve 1/10: lo que ve es la fraccin exacta de arriba, la mejor


aproximacinalflotantedoblede754quepuedeobtener:

>>>.1*2**56
7205759403792794.0

Simultiplicamosesafraccinpor10**30,podemosverelvalor(truncado)desus30dgitosms
significativos:

>>>7205759403792794*10**30/2**56
100000000000000005551115123125L

...loquesignificaqueelvalorexactoalmacenadoenlacomputadoraesaproximadamenteigualal
valordecimal0.100000000000000005551115123125.Redondeandoesoa17dgitossignificativos
dael0.10000000000000001quePythonmuestra(bueno,mostraraencualquierplataformaque
cumplacon754cuyabibliotecaenChagalamejorconversinposibleenentradaysalida...la
tuyaquizsno!).

http://docs.python.org.ar/tutorial/2/floatingpoint.html 4/5
5/1/2017 14.AritmticadePuntoFlotante:ProblemasyLimitacionesTutorialdePythonv2.7.0

http://docs.python.org.ar/tutorial/2/floatingpoint.html 5/5