briast |
04-04-2012 11:14:40 |
Problema con redondeos en doubles
Hola. Tengo un problema con los redondeos cuando la variable es de tipo double. Cuando es extended va bien. El problema se reproduce tanto en Delphi 5 como en Delphi 2010, haciendo la misma prueba en ambos.
No sé de donde viene el problema, pero me gustaría determinar si lo mejor es usar siempre extended. Este problema se agudiza cuando tienes dos doubles y comparas, diciéndote que son diferentes cuando en realidad deberían ser iguales.
Os pongo el código fuente para que lo veáis:
a) Ejemplo de rendondeo por pantalla en un bucle. Tengo en pantalla un botón y dos campos memo.
Código:
procedure TForm1.Button1Click(Sender: TObject);
var pp,pp2:Double;
kk,kk2:Extended;
j:smallint;
begin
{ case RadioGroup1.ItemIndex of
0:Math.SetRoundMode(rmNearest);
1:Math.SetRoundMode(rmUp);
2:Math.SetRoundMode(rmDown);
3:Math.SetRoundMode(rmTruncate);
end; }
memo1.Lines.Clear;
memo2.lines.clear;
pp:=0.005;
kk:=0.005;
pp2:=-0.005;
kk2:=-0.005;
for j := 1 to 100 do
begin
pp:=pp+0.01;
kk:=kk+0.01;
pp2:=pp2-0.01;
kk2:=kk2-0.01;
if formatfloat('0.00',pp)=formatfloat('0.00',kk) then
memo1.Lines.Add(floattostr(pp)+' | '+formatfloat('0.00',pp)+' | '+formatfloat('0.00',kk)+' | '+floattostr(kk))
else memo1.Lines.Add(floattostr(pp)+' | '+formatfloat('0.00',pp)+' | '+formatfloat('0.00',kk)+' | '+floattostr(kk)+' <--- error');
if formatfloat('0.00',pp2)=formatfloat('0.00',kk2) then
memo2.Lines.Add(floattostr(pp2)+' | '+formatfloat('0.00',pp2)+' | '+formatfloat('0.00',kk2)+' | '+floattostr(kk2))
else memo2.Lines.Add(floattostr(pp2)+' | '+formatfloat('0.00',pp2)+' | '+formatfloat('0.00',kk2)+' | '+floattostr(kk2)+' <--- error');
end;
end;
El texto entre comentarios para el radiogroup es para cambiar el método de redondeo en delphi 2010 (unit math), pero el resultado es el mismo (excepto con rmDown). La cuestión es que si se ejecuta sale algo como lo siguiente:
Código:
MEMO1:
0,015 | 0,01 | 0,02 | 0,015 <--- error
0,025 | 0,02 | 0,03 | 0,025 <--- error
0,035 | 0,03 | 0,04 | 0,035 <--- error
0,045 | 0,04 | 0,05 | 0,045 <--- error
0,055 | 0,06 | 0,06 | 0,055
0,065 | 0,07 | 0,07 | 0,065
0,075 | 0,07 | 0,08 | 0,075 <--- error
0,085 | 0,08 | 0,09 | 0,085 <--- error
0,095 | 0,09 | 0,10 | 0,095 <--- error
0,105 | 0,10 | 0,11 | 0,105 <--- error
0,115 | 0,11 | 0,12 | 0,115 <--- error
0,125 | 0,12 | 0,13 | 0,125 <--- error
0,135 | 0,13 | 0,14 | 0,135 <--- error
0,145 | 0,14 | 0,15 | 0,145 <--- error
0,155 | 0,15 | 0,16 | 0,155 <--- error
0,165 | 0,17 | 0,17 | 0,165
0,175 | 0,18 | 0,18 | 0,175
0,185 | 0,19 | 0,19 | 0,185
0,195 | 0,20 | 0,20 | 0,195
0,205 | 0,21 | 0,21 | 0,205
0,215 | 0,22 | 0,22 | 0,215
0,225 | 0,23 | 0,23 | 0,225
0,235 | 0,24 | 0,24 | 0,235
0,245 | 0,25 | 0,25 | 0,245
0,255 | 0,26 | 0,26 | 0,255
0,265 | 0,27 | 0,27 | 0,265
0,275 | 0,28 | 0,28 | 0,275
0,285 | 0,29 | 0,29 | 0,285
0,295 | 0,30 | 0,30 | 0,295
0,305 | 0,31 | 0,31 | 0,305
0,315 | 0,32 | 0,32 | 0,315
0,325 | 0,33 | 0,33 | 0,325
0,335 | 0,34 | 0,34 | 0,335
0,345 | 0,35 | 0,35 | 0,345
0,355 | 0,36 | 0,36 | 0,355
0,365 | 0,37 | 0,37 | 0,365
0,375 | 0,38 | 0,38 | 0,375
0,385 | 0,39 | 0,39 | 0,385
0,395 | 0,40 | 0,40 | 0,395
0,405 | 0,41 | 0,41 | 0,405
0,415 | 0,42 | 0,42 | 0,415
0,425 | 0,43 | 0,43 | 0,425
0,435 | 0,44 | 0,44 | 0,435
0,445 | 0,45 | 0,45 | 0,445
0,455 | 0,46 | 0,46 | 0,455
0,465 | 0,47 | 0,47 | 0,465
0,475 | 0,48 | 0,48 | 0,475
0,485 | 0,49 | 0,49 | 0,485
0,495 | 0,50 | 0,50 | 0,495
0,505 | 0,51 | 0,51 | 0,505
0,515 | 0,52 | 0,52 | 0,515
0,525 | 0,53 | 0,53 | 0,525
0,535 | 0,54 | 0,54 | 0,535
0,545 | 0,55 | 0,55 | 0,545
0,555 | 0,56 | 0,56 | 0,555
0,565 | 0,57 | 0,57 | 0,565
0,575 | 0,58 | 0,58 | 0,575
0,585 | 0,59 | 0,59 | 0,585
0,595 | 0,60 | 0,60 | 0,595
0,605 | 0,61 | 0,61 | 0,605
0,615 | 0,62 | 0,62 | 0,615
0,625 | 0,63 | 0,63 | 0,625
0,635 | 0,64 | 0,64 | 0,635
0,645 | 0,65 | 0,65 | 0,645
0,655 | 0,66 | 0,66 | 0,655
0,665 | 0,67 | 0,67 | 0,665
0,675 | 0,68 | 0,68 | 0,675
0,685 | 0,69 | 0,69 | 0,685
0,695 | 0,70 | 0,70 | 0,695
0,705 | 0,71 | 0,71 | 0,705
0,715 | 0,72 | 0,72 | 0,715
0,725 | 0,73 | 0,73 | 0,725
0,735 | 0,74 | 0,74 | 0,735
0,745 | 0,75 | 0,75 | 0,745
0,755 | 0,76 | 0,76 | 0,755
0,765 | 0,77 | 0,77 | 0,765
0,775 | 0,78 | 0,78 | 0,775
0,785 | 0,79 | 0,79 | 0,785
0,795 | 0,80 | 0,80 | 0,795
0,805 | 0,81 | 0,81 | 0,805
0,815000000000001 | 0,82 | 0,82 | 0,815
0,825000000000001 | 0,83 | 0,83 | 0,825
0,835000000000001 | 0,84 | 0,84 | 0,835
0,845000000000001 | 0,85 | 0,85 | 0,845
0,855000000000001 | 0,86 | 0,86 | 0,855
0,865000000000001 | 0,87 | 0,87 | 0,865
0,875000000000001 | 0,88 | 0,88 | 0,875
0,885000000000001 | 0,89 | 0,89 | 0,885
0,895000000000001 | 0,90 | 0,90 | 0,895
0,905000000000001 | 0,91 | 0,91 | 0,905
0,915000000000001 | 0,92 | 0,92 | 0,915
0,925000000000001 | 0,93 | 0,92 | 0,925 <--- error
0,935000000000001 | 0,94 | 0,93 | 0,935 <--- error
0,945000000000001 | 0,95 | 0,94 | 0,945 <--- error
0,955000000000001 | 0,96 | 0,95 | 0,955 <--- error
0,965000000000001 | 0,97 | 0,96 | 0,965 <--- error
0,975000000000001 | 0,98 | 0,97 | 0,975 <--- error
0,985000000000001 | 0,99 | 0,98 | 0,985 <--- error
0,995000000000001 | 1,00 | 0,99 | 0,995 <--- error
1,005 | 1,01 | 1,01 | 1,005
Como véis hay diferencias entre redondear a dos decimales un double y un extended. Pero lo más extraño de todo es que 0,805 + 0,01 da 0,8150000000001. Aquí empieza otro problema. En el memo2 tenemos:
Código:
MEMO2:
-0,015 | -0,01 | -0,02 | -0,015 <--- error
-0,025 | -0,02 | -0,03 | -0,025 <--- error
-0,035 | -0,03 | -0,04 | -0,035 <--- error
-0,045 | -0,04 | -0,05 | -0,045 <--- error
-0,055 | -0,06 | -0,06 | -0,055
-0,065 | -0,07 | -0,07 | -0,065
-0,075 | -0,07 | -0,08 | -0,075 <--- error
-0,085 | -0,08 | -0,09 | -0,085 <--- error
-0,095 | -0,09 | -0,10 | -0,095 <--- error
-0,105 | -0,10 | -0,11 | -0,105 <--- error
-0,115 | -0,11 | -0,12 | -0,115 <--- error
-0,125 | -0,12 | -0,13 | -0,125 <--- error
-0,135 | -0,13 | -0,14 | -0,135 <--- error
-0,145 | -0,14 | -0,15 | -0,145 <--- error
-0,155 | -0,15 | -0,16 | -0,155 <--- error
-0,165 | -0,17 | -0,17 | -0,165
-0,175 | -0,18 | -0,18 | -0,175
-0,185 | -0,19 | -0,19 | -0,185
-0,195 | -0,20 | -0,20 | -0,195
-0,205 | -0,21 | -0,21 | -0,205
-0,215 | -0,22 | -0,22 | -0,215
-0,225 | -0,23 | -0,23 | -0,225
-0,235 | -0,24 | -0,24 | -0,235
-0,245 | -0,25 | -0,25 | -0,245
-0,255 | -0,26 | -0,26 | -0,255
-0,265 | -0,27 | -0,27 | -0,265
-0,275 | -0,28 | -0,28 | -0,275
-0,285 | -0,29 | -0,29 | -0,285
-0,295 | -0,30 | -0,30 | -0,295
-0,305 | -0,31 | -0,31 | -0,305
-0,315 | -0,32 | -0,32 | -0,315
-0,325 | -0,33 | -0,33 | -0,325
-0,335 | -0,34 | -0,34 | -0,335
-0,345 | -0,35 | -0,35 | -0,345
-0,355 | -0,36 | -0,36 | -0,355
-0,365 | -0,37 | -0,37 | -0,365
-0,375 | -0,38 | -0,38 | -0,375
-0,385 | -0,39 | -0,39 | -0,385
-0,395 | -0,40 | -0,40 | -0,395
-0,405 | -0,41 | -0,41 | -0,405
-0,415 | -0,42 | -0,42 | -0,415
-0,425 | -0,43 | -0,43 | -0,425
-0,435 | -0,44 | -0,44 | -0,435
-0,445 | -0,45 | -0,45 | -0,445
-0,455 | -0,46 | -0,46 | -0,455
-0,465 | -0,47 | -0,47 | -0,465
-0,475 | -0,48 | -0,48 | -0,475
-0,485 | -0,49 | -0,49 | -0,485
-0,495 | -0,50 | -0,50 | -0,495
-0,505 | -0,51 | -0,51 | -0,505
-0,515 | -0,52 | -0,52 | -0,515
-0,525 | -0,53 | -0,53 | -0,525
-0,535 | -0,54 | -0,54 | -0,535
-0,545 | -0,55 | -0,55 | -0,545
-0,555 | -0,56 | -0,56 | -0,555
-0,565 | -0,57 | -0,57 | -0,565
-0,575 | -0,58 | -0,58 | -0,575
-0,585 | -0,59 | -0,59 | -0,585
-0,595 | -0,60 | -0,60 | -0,595
-0,605 | -0,61 | -0,61 | -0,605
-0,615 | -0,62 | -0,62 | -0,615
-0,625 | -0,63 | -0,63 | -0,625
-0,635 | -0,64 | -0,64 | -0,635
-0,645 | -0,65 | -0,65 | -0,645
-0,655 | -0,66 | -0,66 | -0,655
-0,665 | -0,67 | -0,67 | -0,665
-0,675 | -0,68 | -0,68 | -0,675
-0,685 | -0,69 | -0,69 | -0,685
-0,695 | -0,70 | -0,70 | -0,695
-0,705 | -0,71 | -0,71 | -0,705
-0,715 | -0,72 | -0,72 | -0,715
-0,725 | -0,73 | -0,73 | -0,725
-0,735 | -0,74 | -0,74 | -0,735
-0,745 | -0,75 | -0,75 | -0,745
-0,755 | -0,76 | -0,76 | -0,755
-0,765 | -0,77 | -0,77 | -0,765
-0,775 | -0,78 | -0,78 | -0,775
-0,785 | -0,79 | -0,79 | -0,785
-0,795 | -0,80 | -0,80 | -0,795
-0,805 | -0,81 | -0,81 | -0,805
-0,815000000000001 | -0,82 | -0,82 | -0,815
-0,825000000000001 | -0,83 | -0,83 | -0,825
-0,835000000000001 | -0,84 | -0,84 | -0,835
-0,845000000000001 | -0,85 | -0,85 | -0,845
-0,855000000000001 | -0,86 | -0,86 | -0,855
-0,865000000000001 | -0,87 | -0,87 | -0,865
-0,875000000000001 | -0,88 | -0,88 | -0,875
-0,885000000000001 | -0,89 | -0,89 | -0,885
-0,895000000000001 | -0,90 | -0,90 | -0,895
-0,905000000000001 | -0,91 | -0,91 | -0,905
-0,915000000000001 | -0,92 | -0,92 | -0,915
-0,925000000000001 | -0,93 | -0,92 | -0,925 <--- error
-0,935000000000001 | -0,94 | -0,93 | -0,935 <--- error
-0,945000000000001 | -0,95 | -0,94 | -0,945 <--- error
-0,955000000000001 | -0,96 | -0,95 | -0,955 <--- error
-0,965000000000001 | -0,97 | -0,96 | -0,965 <--- error
-0,975000000000001 | -0,98 | -0,97 | -0,975 <--- error
-0,985000000000001 | -0,99 | -0,98 | -0,985 <--- error
-0,995000000000001 | -1,00 | -0,99 | -0,995 <--- error
-1,005 | -1,01 | -1,01 | -1,005
Con lo cual pasa lo mismo con los negativos.
Pero ahora, visto lo visto, pongo otro botón en la pantalla y un label y asocio al botón el código siguiente:
Código:
procedure TForm1.Button2Click(Sender: TObject);
var pp,kk:double;
begin
pp:=0.805;
kk:=0.815;
pp:=pp+0.01;
if pp=kk then label1.caption:='iguales'
else label1.caption:='distintos: ' + FloatToStr(pp)+ ' <> ' + floattostr(kk);
end;
Si pulsas el botón, en lugar de salir en el label el texto "iguales", aparece el texto: distintos 0,815<>0,815
:eek: :confused:
Algo estoy haciendo mal ... esto no puede ser así ...
|