[JAVA] aanpasbare precisie

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Beste tweakers,

Voor een werkje van school moeten we werken met een veld strength.
Dit veld moet een decimaal getal zijn met aanpasbare precisie.
Voor de precisie houden we een constante bij "private static final int STRENGTH_PRECISION = 2"
We werken momenteel met BigDecimals omdat hiervan de precisie op eenvoudige wijze kan aangepast worden.
Echter moeten we een heleboel berekeningen doen met strength (o.a. vermenigvuldigen en delen met gehele getallen) en daarvoor is BigDecimal niet erg handig.
We zouden ook kunnen werken met doubles en hierop DecimalFormat gebruiken. Echter is het aanpassen van de precisie daar een heel stuk minder elegant aangezien we daar niet gewoon het veld STRENGT_PRECISION moeten aanpassen.
Nu zit ik wat rond te googlen en er zijn nog methodes, vb. de double vermenigvuldigen met 100, hier een int van maken en van deze int dan weer een double maken door deling door 100. Dit zorgt echter niet voor de elegantste oplossing.
We zitten hier dus eigenlijk al de hele tijd op te denken en te kloten terwijl dit niet de essentie zou mogen zijn van het werk.
Er zijn hier ongetwijfeld mensen met veel meer ervaring in java dus vroegen wij ons af of er iemand ervaring heeft met gelijkaardige dingen en wat die ons aanraad.

We apprecïeren elke nuttige input.

Bij voorbaat dank :)

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 18:51
Wat zijn precies de eisen met betrekking tot "precisie"? Gaat het om het weergeven van getallen, de precisie waarmee krachten worden opgeslagen, of ook de precisie van interne berekeningen? Dat maakt nogal wat uit.

Als je doubles gebruikt, heb je een min of meer vaste relatieve precisie (niet helemaal omdat je ook denormalized values hebt) maar daardoor heb je een variabele (absolute) precisie. Simpel gezegd: hoe groter je getallen worden, hoe minder cijfers achter de komma je opslaat. Of dat volstaat voor jouw project kan ik niet beoordelen. Als je expliciet gevraagd bent om een instelbare precisie te gebruiken bij je interne berekeningen (dus niet alleen bij de weergave) dan voldoet een double daar niet aan. Als het alleen om de weergave gaat, is het gebruik van doubles juist wél aan te raden, want daar is eenvoudig, snel en redelijk accuraat mee te rekenen

Als je wél de absolute precisie onder controle moet houden, ontkom je niet aan een fixed point representatie. De methode die je zelf geeft (vermenigvuldigen met 100 en dan representeren als een int) is effectief hetzelfde als wat Java al doet in de BigDecimal klasse (behalve dat die klasse ook een oneindig groot bereik heeft). Als je dat wil, zou ik dus aanraden om de BigDecimal klasse te (blijven) gebruiken, dan hoef je die functionaliteit zelf niet opnieuw te implementeren.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
In principe zijn de enige berekeningen die we moeten doen vermenigvuldigen en delen met een geheel getal.
Er wordt in de opdracht ook niet gezegd of we een bepaalde manier van afronden (of afkappen) moeten gebruiken. (wat in onze richting eigenlijk hetzelfde wilt zeggen als "kies een afrondingswijze")

Nu ik je bericht zo doorlees bedoelen wij eigenlijk vooral het voorstellen van getallen.
Wij zijn er nu zo goed als uit dat we doubles gaan gebruiken, en afronden doen we zo:
d = (int)(d * 100 + 0.5) / 100.0;

Moest er iemand nog een suggestie hebben horen we het nog altijd graag :)

Bedankt @Soultaker iig ;)

Acties:
  • 0 Henk 'm!

  • ValHallASW
  • Registratie: Februari 2003
  • Niet online
Suggestie:
Java:
1
d = int(d * 100 + 0.5)/100.0

of, als java die syntax niet ondersteunt:
Java:
1
d = ((int)(d * 100 + 0.5))/100.0

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 18:51
@ValHallASW: de eerste syntax ondersteunt Java niet en de tweede is precies wat tommm. al bedacht had, met een extra paar haakjes. ;)

Het kan ook zonder cast natuurlijk:
Java:
1
d = Math.rint(d*100)/100;

(In theorie nuttig omdat int een kleiner bereik heeft dan double. Dat maakt in de praktijk pas uit als je waarden >2 miljard wil afronden.)

[ Voor 75% gewijzigd door Soultaker op 28-02-2010 22:03 . Reden: Math.rint(), niet Math.round() ]


Acties:
  • 0 Henk 'm!

Verwijderd

Als het gewoon voor de school opdracht is: gewoon BigDecimal gebruiken, dat levert minste gezeik en regels code op.

In het echt: als je niet meer dan 64 bits aan precisie nodig hebt, werk dan gewoon met doubles en rond het voor het weergeven af. Als je wel met extreem grote getallen werkt, gebruik dan BigDecimal met veel te veel digits. Je rond *nooit* tussendoor af. Gewoon niet doen. Anders krijg je zaken als: 1 / 2 * 2 = 0 voor decimals = 0, en je kunt voor elke precisie wel iets verzinnen waardoor het compleet fout gaat.

Dit is alleen als je in Java werkt; normaal zit je toch in matlab, als je een gevoelige berekening (bijv stiff diff. equations) doe kan je gewoon de nauwkeurigheid opschroeven.

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

(jarig!)
Soultaker schreef op zondag 28 februari 2010 @ 21:58:
(In theorie nuttig omdat int een kleiner bereik heeft dan double. Dat maakt in de praktijk pas uit als je waarden >2 miljard wil afronden.)
Waarden groter dan 20 miljoen toch? Door de vermenigvuldiging ga je iig nog sneller naar het einde van het int-bereik toe. Als de precisie groter dan 2 cijfers achter de komma moet zijn wordt het nog erger, bij 5 kan je nog maar 2miljard / 100.000 aan getallen opslaan in je doubles omdat je anders tegen int-overflow aanloopt bij je cast. Met longs heb je dat probleem natuurlijk minder snel.

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Ben ik de enige die bij de OP gewoon het idee krijgt dat de opdracht verkeerd is gelezen en dat de getallen alleen bij het tonen afgerond moeten worden?

https://niels.nu


Acties:
  • 0 Henk 'm!

  • YakuzA
  • Registratie: Maart 2001
  • Niet online

YakuzA

Wat denk je nou zelluf hey :X

Hydra schreef op maandag 01 maart 2010 @ 13:38:
Ben ik de enige die bij de OP gewoon het idee krijgt dat de opdracht verkeerd is gelezen en dat de getallen alleen bij het tonen afgerond moeten worden?
mijn eerste gedachte was inderdaad ook:
C#:
1
Math.Round(Getal, STRENGTH_BLALALA);

waar Getal je BigDecimal, Double, Long of whatever.

Death smiles at us all, all a man can do is smile back.
PSN


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Nu je het zegt, we zijn weer aan het twijfelen geslagen. We gaan er nog eens over nadenken maar gaan eerst wat andere methode's e.d. schrijven, over dit gedeelte hebben we voorlopig genoeg nagedacht.

hartelijk dank voor de input @iedereen iig.
Pagina: 1