|
| Afrunding af en double til en decimal Fra : Allan Bredahl |
Dato : 13-12-00 17:05 |
|
Hej Alle
Jeg har dette : 0.1265464d
og vil afrunde til dette : 0.1
Hvilken metode skal der til for at gøre det ?
På forhånd tak
Allan Bredahl
| |
Ulrik Magnusson (13-12-2000)
| Kommentar Fra : Ulrik Magnusson |
Dato : 13-12-00 19:05 |
|
>
> Jeg har dette : 0.1265464d
> og vil afrunde til dette : 0.1
> Hvilken metode skal der til for at gøre det ?
Et forslag:
double d = 0.1265464d;
d = Math.floor(d * 10) / 10;
Ulrik Magnusson
| |
Thomas Sejr Jensen (13-12-2000)
| Kommentar Fra : Thomas Sejr Jensen |
Dato : 13-12-00 19:15 |
|
Gælder det ikke om at lave sin kode så indviklet som muligt??
"Ulrik Magnusson" <ulrikm@yahoo.com> skrev i en meddelelse
news:3A3836D1.1292CBB@yahoo.com...
> >
> > Jeg har dette : 0.1265464d
> > og vil afrunde til dette : 0.1
> > Hvilken metode skal der til for at gøre det ?
>
> Et forslag:
>
> double d = 0.1265464d;
> d = Math.floor(d * 10) / 10;
>
> Ulrik Magnusson
>
| |
Ulrik Magnusson (13-12-2000)
| Kommentar Fra : Ulrik Magnusson |
Dato : 13-12-00 19:28 |
|
> Gælder det ikke om at lave sin kode så indviklet som muligt??
Jo, det undskylder jeg meget.
double
d=0.1265464d
;
d= Math
.
floor
(
d
*10)/
10;
Ulrik Magnusson
| |
Jesper Sørensen (14-12-2000)
| Kommentar Fra : Jesper Sørensen |
Dato : 14-12-00 12:49 |
|
det burde vel være
double d = 0.1265464d;
d = Math.floor(d * 10+0.5) / 10;
^
for at det virker, din funktion vil altid runde ned.
JS
Ulrik Magnusson <ulrikm@yahoo.com> wrote in message
news:3A3836D1.1292CBB@yahoo.com...
> >
> > Jeg har dette : 0.1265464d
> > og vil afrunde til dette : 0.1
> > Hvilken metode skal der til for at gøre det ?
>
> Et forslag:
>
> double d = 0.1265464d;
> d = Math.floor(d * 10) / 10;
>
> Ulrik Magnusson
>
| |
N/A (13-12-2000)
| Kommentar Fra : N/A |
Dato : 13-12-00 19:52 |
|
| |
Ulrik Magnusson (13-12-2000)
| Kommentar Fra : Ulrik Magnusson |
Dato : 13-12-00 19:52 |
|
> Følgende virker
> double ny=(float) ( (int)(0.1265464*10) ) /10;
> Der kommer dog af en eller anden grund en masse decimaler med (er der nogen
> der kan forklare det?)
Næh, javac regner værdien ud (på compileringstidspunktet), så det er svært at
sige, hvad den har lavet (det må være en fejl). Det eneste bytecode, der
genereres er følgende:
0 ldc2_w #4 <Double 0.10000000149011612>
3 dstore_1
Generer bytecode for den kompilerede klasse K med:
javap -c K
Ulrik Magnusson
| |
Troels Thomsen (13-12-2000)
| Kommentar Fra : Troels Thomsen |
Dato : 13-12-00 22:26 |
|
> double ny=(float) ( (int)(0.1265464*10) ) /10;
> Det skal tilføjes at 0.19 også vil blive afrundet til 0.1, ikke 0.2.
Man kunne jo også afrunde :
double ny=(float) ( (int)(0.1265464*10+0.5) ) /10;
tpt
| |
Lars Dam (14-12-2000)
| Kommentar Fra : Lars Dam |
Dato : 14-12-00 09:30 |
|
On Wed, 13 Dec 2000 18:59:09 +0100, "Thomas Sejr Jensen"
<thomassj@worldonline.dk> wrote:
>Følgende virker
>double ny=(float) ( (int)(0.1265464*10) ) /10;
>
>Der kommer dog af en eller anden grund en masse decimaler med (er der nogen
>der kan forklare det?)
Den korte forklaring:
Det er fordi der kun er et begrænset antal bits til rådighed til
decimalerne - og derfor kan 'skæve' tal, når man snakker 'floating
points' ikke ramme et binært nul præcist; så nede på de yderste
decimaler kan floating point tal være upræcise.
Den lidt længere forklaring:
Decimal bits virker lige som alm. bits, de bliver bare halveret i
stedet for at fordoblet, når man 'tæller baglæns' i bit rækken:
i.e. ved en 4 bits decimal, vil de have værdierne:
1/2 1/4 1/8 1/16
0.5 0.25 0.125 0,0625
Ved 8 bits:
1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256
0.5 0.25 0.125 0,0625 0,03125 0,015625 0,0078125 0,00390625
Jo flere bits der er tilrådighed, jo større præcision.
Så for at repræsentere 0.1 binært, skal man sætte bits således at
brøkerne kommer så tæt på 0.1 som muligt - men hvis man kun har et
begrænset antal bits til rådighed - så kan man kun komme tæt på, og
ikke ramme præcist (med mindre 1/256 (for 8 bits præcision) går op i
den decimal man har)
Så for en 8 bits float bliver 0,1 lagret som:
0,1 ~= 1/16 + 1/32 + 1/256 (00010011 binært)
0,0625 + 0,03125 + 0,00390625 = 0,09765625
0,09765625 er altså tættest på 0,1, hvis man kun bruger 8 bits til
decimaler - det skal lige siges at dette regnestykke er hurtigt gjort
i hånden, så det er med forbehold for regnefejl; eksemplet belyser dog
problemet tilstrækkeligt.
For float vedkommende er der så vidt jeg ved ca. 40 bits til rådighed
for at repræsentere decimaler (af 64 bits) - double nok en 80 bits
præcision (af 128) - hvilket giver en langt højere præcision end 8
bits - derfor de flere decimaler (0.10000000149011612 jvnfr. anden
post i denne tråd)
Den helt præcise forklaring:
Kan i sikkert selv finde i et ieee dokument et eller andet sted.
vh. ld
--
"Time is the fire in which we burn"
| |
Ulrik Magnusson (14-12-2000)
| Kommentar Fra : Ulrik Magnusson |
Dato : 14-12-00 15:29 |
|
> Det er fordi der kun er et begrænset antal bits til rådighed til
> decimalerne - og derfor kan 'skæve' tal, når man snakker 'floating
> points' ikke ramme et binært nul præcist; så nede på de yderste
> decimaler kan floating point tal være upræcise.
Kan du så også forklare hvorfor
double ny = (double) ((int)(0.12*10)) /10;
giver 0.1 og
double ny = (float) ((int)(0.12*10)) /10;
giver 0.10000000149011612
??
(Begge regnes ud på compileringstidspunktet)
Ulrik Magnusson
| |
Lars Dam (14-12-2000)
| Kommentar Fra : Lars Dam |
Dato : 14-12-00 15:59 |
|
On Thu, 14 Dec 2000 14:28:37 GMT, Ulrik Magnusson <ulrikm@yahoo.com>
wrote:
>> Det er fordi der kun er et begrænset antal bits til rådighed til
>> decimalerne - og derfor kan 'skæve' tal, når man snakker 'floating
>> points' ikke ramme et binært nul præcist; så nede på de yderste
>> decimaler kan floating point tal være upræcise.
>
>Kan du så også forklare hvorfor
>
> double ny = (double) ((int)(0.12*10)) /10;
>
>giver 0.1 og
Sikkert fordi double har større præcision og kan ramme 0.1 præcist?
>
> double ny = (float) ((int)(0.12*10)) /10;
>
>giver 0.10000000149011612
Her caster du jo til en float, og ødelægger præcisionen og caster
tilbage - samme fejl, som hvis du castede en long (der har en større
værdi end max_int) tilbage til en int.
>
>??
>(Begge regnes ud på compileringstidspunktet)
>Ulrik Magnusson
vh. ld
--
"Time is the fire in which we burn"
| |
Ulrik Magnusson (16-12-2000)
| Kommentar Fra : Ulrik Magnusson |
Dato : 16-12-00 01:55 |
|
> >Kan du så også forklare hvorfor
> > double ny = (double) ((int)(0.12*10)) /10;
> >giver 0.1 og
> Sikkert fordi double har større præcision og kan ramme 0.1 præcist?
> > double ny = (float) ((int)(0.12*10)) /10;
> >giver 0.10000000149011612
> Her caster du jo til en float, og ødelægger præcisionen og caster
> tilbage - samme fejl, som hvis du castede en long (der har en større
> værdi end max_int) tilbage til en int.
Hvad så med:
float ny = (float) ((int)(0.12*10)) /10;
og
double ny = (double) ((int)(0.12*10)) /10;
som begge giver 0.1.
(Er pointen bare at man skal være forsigtig med flydende tal?)
Ulrik Magnusson
| |
Lars Dam (18-12-2000)
| Kommentar Fra : Lars Dam |
Dato : 18-12-00 12:28 |
|
On Sat, 16 Dec 2000 00:54:38 GMT, Ulrik Magnusson <ulrikm@yahoo.com>
wrote:
>> >Kan du så også forklare hvorfor
>> > double ny = (double) ((int)(0.12*10)) /10;
>> >giver 0.1 og
>> Sikkert fordi double har større præcision og kan ramme 0.1 præcist?
>> > double ny = (float) ((int)(0.12*10)) /10;
>> >giver 0.10000000149011612
>> Her caster du jo til en float, og ødelægger præcisionen og caster
>> tilbage - samme fejl, som hvis du castede en long (der har en større
>> værdi end max_int) tilbage til en int.
>
>Hvad så med:
>float ny = (float) ((int)(0.12*10)) /10;
>og
>double ny = (double) ((int)(0.12*10)) /10;
>
>som begge giver 0.1.
Umiddelbar kan jeg ikke lige give en fornuftig forklaring på det.
>(Er pointen bare at man skal være forsigtig med flydende tal?)
Ja - ihvertfald hvis du skal bruge rigtigt mange decimaler. Hvis ikke
du har brug for flere end den præcision der tilbydes er det ikke noget
problem - ud fra devisen om at hvis du skal bruge en præcision på e.g.
4 decimaler, så er 0.1000 det samme som 0.100000000006
>Ulrik Magnusson
vh. ld
--
"Time is the fire in which we burn"
| |
Ulrik Magnusson (14-12-2000)
| Kommentar Fra : Ulrik Magnusson |
Dato : 14-12-00 15:31 |
|
> Det er fordi der kun er et begrænset antal bits til rådighed til
> decimalerne - og derfor kan 'skæve' tal, når man snakker 'floating
> points' ikke ramme et binært nul præcist; så nede på de yderste
> decimaler kan floating point tal være upræcise.
Kan du så også forklare hvorfor
double ny = (double) ((int)(0.12*10)) /10;
giver 0.1 og
double ny = (float) ((int)(0.12*10)) /10;
giver 0.10000000149011612
??
(Begge regnes ud på compileringstidspunktet)
Ulrik Magnusson
| |
Lars Dam (14-12-2000)
| Kommentar Fra : Lars Dam |
Dato : 14-12-00 16:04 |
|
On Thu, 14 Dec 2000 14:31:21 GMT, Ulrik Magnusson <ulrikm@yahoo.com>
wrote:
>Kan du så også forklare hvorfor
>
> double ny = (double) ((int)(0.12*10)) /10;
>
>giver 0.1 og
>
> double ny = (float) ((int)(0.12*10)) /10;
>
>giver 0.10000000149011612
>
>??
>(Begge regnes ud på compileringstidspunktet)
Mit forrige svar gik på hvorfor du fik så mange decimaler - men jeg
blev lidt i tvivl om du spurgte hvorfor 0.12 kunne blive til 0.1 - det
er også ret simpelt:
Du gør: 0.12*10 = 1.2 - dette caster du så til en int, så bliver
decimalerne 0.2 fjernet og du får 1 - dernæst dividerer du med 10, og
får 0,1 som float - decimal unøjagtigheden finder du grunden til pga.
upræcisionen pga. for få decimal bits.
>Ulrik Magnusson
vh. ld
--
"Time is the fire in which we burn"
| |
|
|