.oisyn schreef op donderdag 27 januari 2011 @ 14:59:
.edit: CodeCaster, wat voor rounding mode gebruik jij? Round to even, zoals het hoort?
Ik kom met doubles (53 bits mantissa) op dit lijstje: 1.50, 42.50, 53.50, 86.50, 91.50
En met floats (24 bits mantissa) op dit lijstje: 24.50, 43.50, 52.50, 92.50, 96.50, 99.50
Ik had een fout gemaakt in m'n code, zag dat ik in plaats van een currency als teller een double gebruikte. Drie keer raden wat daarmee gebeurt als je er tienduizend keer 0.01 bij optelt.
Heb nu deze reeks uit weten te voeren:
1.50, 2.50, 4.50, 5.50, 8.50, 9.50, 13.50, 14.50, 15.50, 16.50, 21.50, 23.50, 25.50, 27.50, 30.50, 32.50, 34.50, 36.50, 39.50, 41.50, 42.50, 45.50, 48.50, 49.50, 52.50, 53.50, 55.50, 56.50, 59.50, 60.50, 63.50, 66.50, 67.50, 70.50, 73.50, 74.50, 77.50, 78.50, 80.50, 81.50, 84.50, 86.50, 89.50, 92.50, 94.50, 95.50, 97.50, 98.50
Met de volgende code, feel free to comment:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| var
floatBedrag: double;
currencyBedrag: currency;
floatBTW: double;
floatBTWBedrag: double;
currencyBTWBedrag: currency;
begin
DecimalSeparator := '.';
ProbleemGetallenMemo.Text := '';
floatBTW := 19.00;
currencyBedrag := 0.00;
repeat
floatBedrag := currencyBedrag;
floatBTWBedrag := floatBedrag * (floatBTW / 100);
currencyBTWBedrag := floatBedrag * (floatBTW / 100);
if (FormatFloat('#0.00', floatBTWBedrag) <> FormatFloat('#0.00', currencyBTWBedrag)) then
begin
ProbleemGetallenMemo.Text := ProbleemGetallenMemo.Text + FormatFloat('#0.00', currencyBedrag) + ', ';
end;
currencyBedrag := currencyBedrag + 0.01;
until (currencyBedrag > 100);
end; |
Het zou ook best aan de FormatFloat-functie kunnen liggen in dit geval (en dan is de oorzaak van het probleem van m'n oorspronkelijke post, hoewel ik het probleem niet bij name noem, niet direct te wijten aan het gebruik van floats maar meer aan de methode van afronding, maar in de oorspronkelijke code wordt die op exact deze wijze gebruikt), maar hoe die precies werkt volg ik niet, want die roept uiteindelijk zo'n 300 regels assembly aan in FloatToTextFmt.
In C# krijg ik inderdaad dezelfde getallen als jij bij een double. 1,50, 42,50, 53,50, 86,50, 91,50:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| double floatBedrag;
decimal decimalBedrag;
double floatBTW;
double floatBTWBedrag;
decimal decimalBTWBedrag;
floatBTW = 19.00f;
decimalBedrag = 0.00m;
do
{
floatBedrag = (double)decimalBedrag;
floatBTWBedrag = floatBedrag * (floatBTW / 100);
decimalBTWBedrag = (decimal)(floatBedrag * (floatBTW / 100));
if ((decimal)Math.Round(floatBTWBedrag, 2) != (Math.Round(decimalBTWBedrag, 2)))
{
Console.Write(decimalBedrag + ", ");
}
decimalBedrag = decimalBedrag + 0.01m;
} while (decimalBedrag <= 100); |
Bij gebruik van een float wel weer een aanzienlijk langere reeks, maar anders dan in Delphi. Waar zijn die zwevendekommagetallen nou eigenlijk goed voor, behalve 3D-berekeningen?
[
Voor 15% gewijzigd door
CodeCaster op 27-01-2011 23:26
]