|
| Forkerte dicimaler Fra : Martin Ehmsen |
Dato : 20-02-01 10:54 |
|
Hej derude...
Jeg har et meget underligt problem, med mit java program. Pointen er at
det skal indlaese nogle tal fra en fil og udskrive gennemsnittet. Det
goer jeg ved at laese alle tal og laegge dem sammen, samtidig med at jeg
laeser antallet af tal (meget lige til, let program). Jeg faar ogsaa den
rigtige sum og det rigtige antal tal; men naar jeg laver divisionen af
disse to tal og udskriver det, saa faar jeg noget som er helt hen i
vejret. Nemlig at 128.3 delt med 5 er 25.660000000000004
Jeg har vedlagt java-filen, samt den fil som jeg laeser ind fra, samt
det output jeg faar fra koerslen paa min (RedHat 7.0 kernel 2.4.1 med
jdk1.3). Det giver i oevrigt samme resultat naar jeg koere det pa en
anden linux box.
Jeg savner en forklaring...
Mvh Thames
=====Projekt.java=====
import java.io.*;
public class Projekt
{
public static void main( String[] args )
{
final String FIL_NAVN = "taldata";
String line;
double value, sum = 0.0;
int antaltal = 0, antallinier = 0;
try {
FileReader fr = new FileReader( FIL_NAVN );
BufferedReader inFile = new BufferedReader( fr );
while( (line = inFile.readLine()) != null ) {
antallinier++;
try {
value = Double.parseDouble( line );
System.out.println( value );
sum += value;
antaltal++;
}
catch( NumberFormatException exception ) {
System.out.println( "Linie " + antallinier + " er
ikke et korrekt tal!" );
}
}
inFile.close();
System.out.println( "Summen er: " + sum );
System.out.println( "Antal tal er: " + antaltal );
if( antaltal != 0 ) {
System.out.println( "Gennemsnittet er: " + (sum /
antaltal) );
}
else
System.out.println( "Umuligt at beregne et gennemsnit.
Indtast nogle tal!" );
}
catch( FileNotFoundException exception ) {
System.out.println( "Filen " + FIL_NAVN + " eksistere
tilsyneladende ikke!" );
}
catch( IOException exception ) {
System.out.println( "Der opstod foelgende fejl under
laesningen af filen " + FIL_NAVN + ":" + exception);
}
}
}
=====taldata=====
7.1
6.0
2.0
100.7
bent
12.5
=====Output fra en koersel=====
7.1
6.0
2.0
100.7
Linie 5 er ikke et tal!
12.5
Summen er: 128.3
Antal tal er: 5
Gennemsnittet er: 25.660000000000004
| |
Allan Unnerup (20-02-2001)
| Kommentar Fra : Allan Unnerup |
Dato : 20-02-01 11:45 |
|
>Jeg har et meget underligt problem, med mit java program. Pointen er at
>det skal indlaese nogle tal fra en fil og udskrive gennemsnittet. Det
>goer jeg ved at laese alle tal og laegge dem sammen, samtidig med at jeg
>laeser antallet af tal (meget lige til, let program). Jeg faar ogsaa den
>rigtige sum og det rigtige antal tal; men naar jeg laver divisionen af
>disse to tal og udskriver det, saa faar jeg noget som er helt hen i
>vejret. Nemlig at 128.3 delt med 5 er 25.660000000000004
>Jeg savner en forklaring...
Det ser da meget fornuftigt ud. Når du regner med tal, der ikke kan
repræsenteres præcist i det binære talsystem, vil du få en lille fejl på det
sidste ciffer. Det kan ikke være anderledes.
Det svarer lidt til, at du skal skrive tallet 17, men kun må benytte lige
tal. Så bliver du nødt til enten at skrive 16 eller 18, altså får du en fejl
på sidste ciffer.
Hilsen Allan
| |
Martin Ehmsen (20-02-2001)
| Kommentar Fra : Martin Ehmsen |
Dato : 20-02-01 11:55 |
|
Allan Unnerup wrote:
> Det ser da meget fornuftigt ud. Når du regner med tal, der ikke kan
> repræsenteres præcist i det binære talsystem, vil du få en lille fejl på det
> sidste ciffer. Det kan ikke være anderledes.
>
> Det svarer lidt til, at du skal skrive tallet 17, men kun må benytte lige
> tal. Så bliver du nødt til enten at skrive 16 eller 18, altså får du en fejl
> på sidste ciffer.
Kan du saa ikke forklare mig, hvorfor min lommeregner kan regne 128.3
delt med 5 ud, og stadig give det rigtige svar: 25.66
Bruger den da ikke det binaere talsystem.
Hvis man kan faa en lommeregner til det, hvorfor kan java saa ikke???
Det virker altsaa totalt taabeligt paa mig.
Det sjove er at programmet giver det rigtige svar ved andre vaerdier
(ogsaa decimalbroeker).
Thames
| |
Dennis Thrysøe (20-02-2001)
| Kommentar Fra : Dennis Thrysøe |
Dato : 20-02-01 12:26 |
|
Martin Ehmsen wrote:
> Allan Unnerup wrote:
>
>> Det ser da meget fornuftigt ud. Når du regner med tal, der ikke kan
>> repræsenteres præcist i det binære talsystem, vil du få en lille fejl på det
>> sidste ciffer. Det kan ikke være anderledes.
>>
>> Det svarer lidt til, at du skal skrive tallet 17, men kun må benytte lige
>> tal. Så bliver du nødt til enten at skrive 16 eller 18, altså får du en fejl
>> på sidste ciffer.
>
>
> Kan du saa ikke forklare mig, hvorfor min lommeregner kan regne 128.3
> delt med 5 ud, og stadig give det rigtige svar: 25.66
> Bruger den da ikke det binaere talsystem.
> Hvis man kan faa en lommeregner til det, hvorfor kan java saa ikke???
> Det virker altsaa totalt taabeligt paa mig.
> Det sjove er at programmet giver det rigtige svar ved andre vaerdier
> (ogsaa decimalbroeker).
Måske lommeregneren udregner et ekstra decimal, som ikke vises?
-dennis
| |
Allan Unnerup (20-02-2001)
| Kommentar Fra : Allan Unnerup |
Dato : 20-02-01 16:57 |
|
>Kan du saa ikke forklare mig, hvorfor min lommeregner kan regne 128.3
>delt med 5 ud, og stadig give det rigtige svar: 25.66
Nu bevæger vi os vist lidt uden for Java, men jeg vil tro, at der i
vejledningen til din lommeregner står hvilken præcision den regner med. Den
vil givetvis være større end de 10? cifre, der vises på din lommeregner.
Hilsen Allan
| |
Bertel Lund Hansen (20-02-2001)
| Kommentar Fra : Bertel Lund Hansen |
Dato : 20-02-01 18:16 |
|
Martin Ehmsen skrev:
>Hvis man kan faa en lommeregner til det, hvorfor kan java saa ikke?
Det er ikke Javas skyld. Ethvert programmeringssprog vil løbe ind
i tilsvarende problemer, og det er fundamentalt for computere (og
lommeregnere) med et begrænset antal cifre.
Det er banalt at man ikke kan stole på en test som:
if (værdi==0) ...
hvis værdi er af typen double (eller en anden float-type).
Det er vel muligt at skære de sidste decimaler af? Så bliver
resultatet 'rigtigt'.
>Det sjove er at programmet giver det rigtige svar ved andre vaerdier
>(ogsaa decimalbroeker).
Ikke ved *alle* andre beregninger.
--
Bertel http://lundhansen.dk/bertel/
FIDUSO: http://fiduso.dk/
| |
Esben Mose Hansen (24-02-2001)
| Kommentar Fra : Esben Mose Hansen |
Dato : 24-02-01 10:45 |
|
Martin Ehmsen wrote:
> Allan Unnerup wrote:
>
>
> Kan du saa ikke forklare mig, hvorfor min lommeregner kan regne 128.3
> delt med 5 ud, og stadig give det rigtige svar: 25.66
> Bruger den da ikke det binaere talsystem.
> Hvis man kan faa en lommeregner til det, hvorfor kan java saa ikke???
> Det virker altsaa totalt taabeligt paa mig.
>
Som andre har skrevet, arbejder næsten alle lommeregnere med 3 skjulte
cifre. Men det er ikke forklaringen her. Problemet er at du forsøger at
regne med decimaltal som beinære tal, hvilket generelt er en dårlig idé,
med mindre hastighed er vigtigere end præcision. Istedet bør du finde en
klasse der kan regne med decimaltal. Det der undrer mig er at jeg ikke
kunne finde en sådan indbygget i java. Kan det virkeligt passe?
Nej det kan ej. Klassen hedder java.math.BigDecimal Scale er hvor
mange decimaler der skal være efter kommaet. Husk at sætte den til noget
fornuftigt.
mvh. Esben
| |
Peter Hagstrøm (20-02-2001)
| Kommentar Fra : Peter Hagstrøm |
Dato : 20-02-01 18:38 |
|
"Martin Ehmsen" <ehmsen@imada.sdu.dk> wrote in message
news:3A923ECB.12F648E9@imada.sdu.dk...
> Hej derude...
> Jeg har et meget underligt problem, med mit java program. Pointen er at
> det skal indlaese nogle tal fra en fil og udskrive gennemsnittet. Det
> goer jeg ved at laese alle tal og laegge dem sammen, samtidig med at jeg
> laeser antallet af tal (meget lige til, let program). Jeg faar ogsaa den
> rigtige sum og det rigtige antal tal; men naar jeg laver divisionen af
> disse to tal og udskriver det, saa faar jeg noget som er helt hen i
> vejret. Nemlig at 128.3 delt med 5 er 25.660000000000004
Grunden er, at det er svært at repræsentere komma tal i et tal system
der ikke har komma tal. Løsning kan, i det her tilfælde, være at mindske
præcisionen. I stedet for at bruge double, så bruge en float:
Følgende kode:
/* CODE */
public static void main( String args[] ) {
float floatnumber = (float)128.3;
double doublenumber = 128.3;
System.out.println( "Float number:" + floatnumber/5 );
System.out.println( "Double number:" + doublenumber/5 );
}
/* END CODE */
giver på mit system (win2k) følgende resultat:
Float number:25.66
Double number:25.660000000000004
Det kan godt virke lidt paradoxalt men float kan nogen gange være
god at bruge til sådant et formål.
Hvis det kun er for syns skyld, kan du jo også køre den igennem
DecimalFormat klassen eller lign.
> Jeg har vedlagt java-filen, samt den fil som jeg laeser ind fra, samt
> det output jeg faar fra koerslen paa min (RedHat 7.0 kernel 2.4.1 med
> jdk1.3). Det giver i oevrigt samme resultat naar jeg koere det pa en
> anden linux box.
> Jeg savner en forklaring...
| |
Lars Dam (21-02-2001)
| Kommentar Fra : Lars Dam |
Dato : 21-02-01 09:54 |
|
On Tue, 20 Feb 2001 10:54:19 +0100, Martin Ehmsen
<ehmsen@imada.sdu.dk> wrote:
>Hej derude...
>Jeg har et meget underligt problem, med mit java program. Pointen er at
Det er ikke så underligt...
>det skal indlaese nogle tal fra en fil og udskrive gennemsnittet. Det
>goer jeg ved at laese alle tal og laegge dem sammen, samtidig med at jeg
>laeser antallet af tal (meget lige til, let program). Jeg faar ogsaa den
>rigtige sum og det rigtige antal tal; men naar jeg laver divisionen af
>disse to tal og udskriver det, saa faar jeg noget som er helt hen i
>vejret. Nemlig at 128.3 delt med 5 er 25.660000000000004
Se en forklaring jeg skrev for nogen tid siden:
http://groups.google.com/groups?q=lars+%2Bdam+decimal&hl=en&lr=&safe=off&rnum=1&seld=952127246&ic=1
vh. ld
--
"Time is the fire in which we burn"
| |
Carsten Sørensen (21-02-2001)
| Kommentar Fra : Carsten Sørensen |
Dato : 21-02-01 12:08 |
|
"Lars Dam" <lars_simple_spam_protection_dam@post2.tele.dk> wrote in message
news:5f079to1lif7oktd4n691l885c4e4tgunm@4ax.com...
> Se en forklaring jeg skrev for nogen tid siden:
>
>
http://groups.google.com/groups?q=lars+%2Bdam+decimal&hl=en&lr=&safe=off&rnu
m=1&seld=952127246&ic=1
Kort bemærkning til en udmærket forklaring:
float er 32 bits (1 tegn, 8 eksponent, 23 mantisse [effektivt er det 24 når
man tæller det implicitte ettal])
double er 64 (1, 11, 52[53])
Carsten Sørensen
| |
|
|