/ Forside / Teknologi / Udvikling / Java / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Java
#NavnPoint
molokyle 3688
Klaudi 855
strarup 740
Forvirret 660
gøgeungen 500
Teil 373
Stouenberg 360
vnc 360
pmbruun 341
10  mccracken 320
nøjagtighed
Fra : René Holdgard Wilhar~


Dato : 27-10-01 12:36

Hej.

Hvis jeg laver denne her:

double d = 4.1;
double rest = d % 1;

Så ville jeg mene at rest = 0.1

Men jeg får dette resultat:
0.09999999999999964

Hvorfor ?
Hvad gør jeg ved det ?

René







 
 
Bertel Lund Hansen (27-10-2001)
Kommentar
Fra : Bertel Lund Hansen


Dato : 27-10-01 13:56

René Holdgard Wilhardt skrev:

>double rest = d % 1;

>Så ville jeg mene at rest = 0.1

Ja, men ikke i en computer.

>Men jeg får dette resultat:
>0.09999999999999964

Ja.

>Hvorfor ?

Fordi computeren ikke kan regne uendeligt nøjagtigt, og
float-typer lagres som en binær kode. Den passer ikke specielt
godt med titalssystemet. Derfor er der ofte en lille forskel.
   
--
Bertel
http://lundhansen.dk/bertel/   FIDUSO: http://fiduso.dk/

René Holdgard Wilhar~ (27-10-2001)
Kommentar
Fra : René Holdgard Wilhar~


Dato : 27-10-01 14:11


> Fordi computeren ikke kan regne uendeligt nøjagtigt, og
> float-typer lagres som en binær kode. Den passer ikke specielt
> godt med titalssystemet. Derfor er der ofte en lille forskel.
Ok. Jeg skulle bruge den til at tælle hvor mange decimaler der er i en
double.
Jeg går ud fra at der må findes en måde at gøre det på. Er der et hint ?
René



Andreas Andersen (27-10-2001)
Kommentar
Fra : Andreas Andersen


Dato : 27-10-01 14:17

> Ok. Jeg skulle bruge den til at tælle hvor mange decimaler der er i en
> double.
> Jeg går ud fra at der må findes en måde at gøre det på. Er der et hint ?

Du kunne evt. caste den til en string og finde ud af hvilken plads
punktummet står på, men ok - ikke særlig smukt.....

Andreas



Bertel Lund Hansen (27-10-2001)
Kommentar
Fra : Bertel Lund Hansen


Dato : 27-10-01 14:25

René Holdgard Wilhardt skrev:

>Ok. Jeg skulle bruge den til at tælle hvor mange decimaler der er i en
>double.

Det er der to svar på, for du kan tælle de decimaler der overhovedet spyttes
ud, men du kan også tælle pålidelige decimaler.

>Jeg går ud fra at der må findes en måde at gøre det på. Er der et hint ?

Hvis du bare vil have fat i decimalerne, kan du danne en streng der består af
cifrenes tegn og så bruge dens length(). Men du får altså decimalerne på den
'fysiske' double, og ikke den matematiske.

double tal = 4.1;
System.out.println("Tal har "+(new Double(tal)).toString().length()+" cifre");

Du kan nok selv pynte på den for kommaet tælles som et ciffer.

--
Bertel
http://lundhansen.dk/bertel/   FIDUSO: http://fiduso.dk/

Christian Holm (27-10-2001)
Kommentar
Fra : Christian Holm


Dato : 27-10-01 16:40

"René Holdgard Wilhardt" <rhw@cadeye.dk> wrote in message
news:3bda9af5$0$25367$edfadb0f@dspool01.news.tele.dk...
> Hvad gør jeg ved det ?

Bruger BigDecimal klassen til at regne med i stedet. Den kan regne
"præcist".

Christian Holm



René Holdgard Wilhar~ (27-10-2001)
Kommentar
Fra : René Holdgard Wilhar~


Dato : 27-10-01 17:18

Her er hvad jeg gjorde:

String s = new Double( d).toString();
StringTokenizer st = new StringTokenizer( s, ".");
String nyS ="";

while( st.hasMoreTokens())
{
nyS = st.nextToken();
}
int pot = nyS.length();

Jeg er meget ny i det her så jeg modtager gerne en kommentar på den.



"Christian Holm" <cho@cubitech.dk> wrote in message
news:3bdad53e$0$220$edfadb0f@dspool01.news.tele.dk...
> "René Holdgard Wilhardt" <rhw@cadeye.dk> wrote in message
> news:3bda9af5$0$25367$edfadb0f@dspool01.news.tele.dk...
> > Hvad gør jeg ved det ?
>
> Bruger BigDecimal klassen til at regne med i stedet. Den kan regne
> "præcist".
>
> Christian Holm
>
>



Jesper Søndergaard J~ (28-10-2001)
Kommentar
Fra : Jesper Søndergaard J~


Dato : 28-10-01 00:20

> Her er hvad jeg gjorde:
>
> String s = new Double( d).toString();
> StringTokenizer st = new StringTokenizer( s, ".");
> String nyS ="";
>
> while( st.hasMoreTokens())
> {
> nyS = st.nextToken();
> }
> int pot = nyS.length();
>
> Jeg er meget ny i det her så jeg modtager gerne en kommentar på den.

Det ser fint ud, så vidt jeg kan se. I dette tilfælde kunne det også gøres
således:

String s = Double.toString(d);
int pot = s.substring(s.indexOf(".")+1).length()-(s.endsWith(".0")? 1 : 0);

"-(s.endsWith(".0")? 1 : 0)" gør at pot ved heltal bliver 0.
Jesper



Ulrik Magnusson (30-10-2001)
Kommentar
Fra : Ulrik Magnusson


Dato : 30-10-01 23:48



"René Holdgard Wilhardt" wrote:

> Hej.
>
> Hvis jeg laver denne her:
>
> double d = 4.1;
> double rest = d % 1;
>
> Så ville jeg mene at rest = 0.1
>
> Men jeg får dette resultat:
> 0.09999999999999964
>
> Hvorfor ?

Hermed et forsøg på en lidt mere uddybende forklaring:

% operatoren defineres på følgende måde (kun essensen) i Java Language
Specification:
(http://java.sun.com/docs/books/jls/first_edition/html/15.doc.html#239829)

"the floating-point remainder r from the
division of a dividend n by a divisor d is defined by the
mathematical relation r = n-d*q where q is an integer [...]
whose magnitude is as large as possible without
exceeding the magnitude of the true mathematical quotient of
n and d."

vi får så (q=4):

4.1 % 1 = 4.1 - 1 * 4 = 4.1 - 4

4.1-4 defineres så til at skulle give et IEEE 754 resultat
(http://java.sun.com/docs/books/jls/first_edition/html/4.doc.html#9249)
- and the plot thickens:

I IEEE 754 repræsenteres double værdier som 1 fortegnsbit, 11
eksponentbits og 52 'betydende' bits.

Værdien af et flydende tal er så defineret til at være

((-1)^fortegn) * (1+betydende) * (2^(eksponent-1023))

De betydende regnes ud fra venstre mod højre som en sum af
negative 2-potenser. Eks.

101 = 2^-1 + 2^-3,
001 = 2^-3 og
011 = 2^-2 + 2^-3

Hvis vi så i stedet for 52 betydende bits bruger 3, bliver den nærmeste
representation af 0.1 følgende mønster:

sign: eksponent: betydende:
0 01111111011 011

Dette er dog ikke 0.1 men 0.859375, da

((-1)^0)) //fortegn
* (1 + (0*2^-1) + (1*2^-2) + (1*2^-3)) // betydende
* (2^(1019-1023)) // eksponent

= 1 * (1.375) * (0.625)

= 0.859375

0.1 vil altså altid blive representeret som 0.859375 med 3 betydende
bits.
Situationen med 52 betydende bits er den samme - man skal bare fælde en
regnskov for at regne den ud i hånden.

Ulrik Magnusson


Brian Matzon (31-10-2001)
Kommentar
Fra : Brian Matzon


Dato : 31-10-01 08:57

"Ulrik Magnusson" <ulrikm@yahoo.com> wrote in message news:3BDF2E1B.F86FF7B3@yahoo.com...
<SNIP>
> Hermed et forsøg på en lidt mere uddybende forklaring:
<SNIP>

Jeg kender godt til problemet med afrundings fejl af
floating point tal, men ikke i så store detaljer.
Tak for en god forklaring!

/Brian Matzon



Ulrik Magnusson (31-10-2001)
Kommentar
Fra : Ulrik Magnusson


Dato : 31-10-01 11:43

Ulrik Magnusson wrote:

En mindre 'unøjagtighed' sneg sig vist ind..

> I IEEE 754 repræsenteres double værdier som 1 fortegnsbit, 11
> eksponentbits og 52 'betydende' bits.
>
> Værdien af et flydende tal er så defineret til at være

Herover skulle der have stået 'Værdien af en double er så
defineret til at være', da 1023 i nedenstående skiftes ud med 127
når der bruges float

> ((-1)^fortegn) * (1+betydende) * (2^(eksponent-1023))

og så slipper jeg vist ikke for at forklare bias:

127 og 1023 kaldes bias og har den betydning at positive
eksponenter "ser" store ud i forhold til negative, når der bruges
2-komplement til eksponent - fx (uden bias, 1 fortegnsbit,
2 eksponentbits og 1 betydende bit):

0 11 0 = ((-1) ^ 0) * (1 + 0) * (2 ^ -1) = 1 * 1 * 0.5 = 0.5
0 01 0 = ((-1) ^ 0) * (1 + 0) * (2 ^ 1) = 1 * 1 * 1 = 1

- 0.5 "ser" altså umiddelbart større ud end 1, men med bias 2
( dvs. 2 ^ (antal eksponentbits - 1) ) ser det sådan ud:

0 01 0 = ((-1) ^ 0) * (1 + 0) * (2 ^ (1-2)) = 1 * 1 * 0.5 = 0.5
0 10 0 = ((-1) ^ 0) * (1 + 0) * (2 ^ (2-2)) = 1 * 1 * 1 = 1


Her er et par links:

"IEEE Standard 754 Floating Point Numbers":
http://research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html

"What Every Computer Scientist Should Know About Floating-Point
Arithmetic":
http://cch.loria.fr/documentation/IEEE754/ACM/goldberg.pdf

og en opsang:

"How JAVA's Floating-Point Hurts Everyone Everywhere":
http://cch.loria.fr/documentation/IEEE754/wkahan/JAVAhurt.pdf

Ulrik Magnusson


Thorbjørn Ravn Ander~ (31-10-2001)
Kommentar
Fra : Thorbjørn Ravn Ander~


Dato : 31-10-01 00:08

"René Holdgard Wilhardt" wrote:
>
> Hej.
>
> Hvis jeg laver denne her:
>
> double d = 4.1;
> double rest = d % 1;
>
> Så ville jeg mene at rest = 0.1
>
> Men jeg får dette resultat:
> 0.09999999999999964
>
> Hvorfor ?
> Hvad gør jeg ved det ?

Afrundingsfejl. Når man laver den slags ting, kan man ikke forvente
helt eksakte reusltater. Grunden er oftest at et givent tal ikke kan
repræsenteres helt præcist internt.
--
Thorbjørn Ravn Andersen "...plus... Tubular Bells!"
http://bigfoot.com/~thunderbear

Søg
Reklame
Statistik
Spørgsmål : 177558
Tips : 31968
Nyheder : 719565
Indlæg : 6408927
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste