[C# 2.0] Bepalen # getallen achter de komma

Pagina: 1
Acties:
  • 2.532 views sinds 30-01-2008
  • Reageer

  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 11:02
Ik heb een routine

code:
1
2
3
public FunctieX(double getalA, double getalB, double verwachteResultaat)
{
}


Met getalA en getalB doe ik een berekening. Nu levert deze uitkomst een getal op met veel decimalen (> 8 decimalen).

De binnenkomende verwachteResultaat is van een beperkte precisie. De ene keer is het met 7 achter de komma, de andere keer 8, dit varieert dus. Nu wil ik eerst mijn onafgeronde resultaat afronden op het hetzelfde aantal decimalen van verwachteResultaat. Daarmee vergelijk ik de waarden.

Ik wil dus een routine hebben die mij het aantal decimalen teruggeeft van een willekeurige double. Daarmee ga ik de Math.Round routine in.

Verwijderd

Converteren naar een string, en het aantal karakters achter de punt tellen ?

  • Zr40
  • Registratie: Juli 2000
  • Niet online

Zr40

Moderator General Chat

heeft native IPv6

Je kan beter resultaat van verwachteResultaat aftrekken, en kijken of het verschil klein genoeg is.

  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 11:02
Zr40 schreef op donderdag 05 april 2007 @ 14:19:
Je kan beter resultaat van verwachteResultaat aftrekken, en kijken of het verschil klein genoeg is.
is ook een goed idee! De klant gaf al aan dat de precisie niet er zo heel veel om deed, bij een gelijkenis bij 4 achter de komma was ie al tevreden.




code:
1
2
3
4
5
6
7
8
double verschil= Math.Abs(resultaat - verwachteResultaat);

if (verschil> 0.00001)
{
  Assert.Fail(string.Format(CultureInfo.CurrentUICulture, 
       "Test gefaald, verwacht resultaat = {0}, resultaat = {1}", 
     verwachteResultaat, resultaat));
}

[ Voor 31% gewijzigd door DrDelete op 05-04-2007 14:34 ]


  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 17-10 16:43
Je geeft aan dat precisie niet belangrijk is, maar ik snap eigenlijk niet waarom je voor je double's even veel getallen achter de komma wil hebben (ik dacht toch dat je geen runtime error krijgt bij verschillend aantal getallen achter de komma).

Waarom reken je niet gewoon door met dit:

getal1 = 1,0001
getal2 = 0,000123
getal1+2= 1,000223

Dit zou veel preciezer zijn dan op jouw manier waar je op 1,0002 uitkomt.

Je kunt altijd nog op het allerlaatste afronden, maar ik zou (persoonlijk) nooit tussendoor afronden, vooral ook omdat het het programma op de achtergrond niks uit maakt. De adres grote blijft het zelfde. Ik denk zelfs dat je performance lichtelijk verminderd als je een routine inbouwt om af te ronden voor dat je bij het eindresultaat bent.

(als ik je verkeerd begrepen heb, my bad ik baseerde me op dit stukje uit je tekst
Nu wil ik eerst mijn onafgeronde resultaat afronden op het hetzelfde aantal decimalen van verwachteResultaat. Daarmee vergelijk ik de waarden.
Edit: * roy-t heeft er stiekem 1,... + 0,.. van gemaakt, maar vreest nu wel voor zijn wiskunde examen.

Edit2: Ah ik begrijp nu waarom je dit wilt doen =)

[ Voor 7% gewijzigd door roy-t op 06-04-2007 17:23 ]

~ Mijn prog blog!


  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 11:02
therat10430 schreef op donderdag 05 april 2007 @ 14:43:
Je geeft aan dat precisie niet belangrijk is, maar ik snap eigenlijk niet waarom je voor je double's even veel getallen achter de komma wil hebben (ik dacht toch dat je geen runtime error krijgt bij verschillend aantal getallen achter de komma).

Waarom reken je niet gewoon door met dit:

getal1 = 1,0001
getal2 = 1,000123
getal1+2= 1,000223

Dit zou veel preciezer zijn dan op jouw manier waar je op 1,0002 uitkomt.

Je kunt altijd nog op het allerlaatste afronden, maar ik zou (persoonlijk) nooit tussendoor afronden, vooral ook omdat het het programma op de achtergrond niks uit maakt. De adres grote blijft het zelfde. Ik denk zelfs dat je performance lichtelijk verminderd als je een routine inbouwt om af te ronden voor dat je bij het eindresultaat bent.

(als ik je verkeerd begrepen heb, my bad ik baseerde me op dit stukje uit je tekst

[...]
Mijn rekenroutine rekent de meest precieze getal uit (het is een deelroutine). Echter... ik heb input data van de klant gekregen die niet deze zelfde precisie heeft. Ik wil met mijn unit tests een greep doen uit de inputdata van de klant en daar mijn code mee checken.

Verwijderd

therat10430 schreef op donderdag 05 april 2007 @ 14:43:
Je geeft aan dat precisie niet belangrijk is, maar ik snap eigenlijk niet waarom je voor je double's even veel getallen achter de komma wil hebben (ik dacht toch dat je geen runtime error krijgt bij verschillend aantal getallen achter de komma).

Waarom reken je niet gewoon door met dit:

getal1 = 1,0001
getal2 = 1,000123
getal1+2= 1,000223

Dit zou veel preciezer zijn dan op jouw manier waar je op 1,0002 uitkomt.

Je kunt altijd nog op het allerlaatste afronden, maar ik zou (persoonlijk) nooit tussendoor afronden, vooral ook omdat het het programma op de achtergrond niks uit maakt. De adres grote blijft het zelfde. Ik denk zelfs dat je performance lichtelijk verminderd als je een routine inbouwt om af te ronden voor dat je bij het eindresultaat bent.

(als ik je verkeerd begrepen heb, my bad ik baseerde me op dit stukje uit je tekst

[...]
omdat dit wiskundig incorrect is...

het getal 1,000223 geeft aan dat er een precicie is van +/- 0,0000005

als de getallen 1,0001 (precicie 0,00005, dus min 1,00005 en max 1,00015) en 1,000123 op gaat tellen met de noukeurigheid van het 2e getal kan de uitkomst bijvoorbeeld 1,00005 + 1,000123 = 1,000173 zijn.. en dat gaat buiten de gestelde precicie van +/-0,0000005.

dus bij verschillende noukeurigheden optellen altijd het aantal significante getallen van de minst noukeurige nemen!

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 08:51

NetForce1

(inspiratie == 0) -> true

Verwijderd schreef op donderdag 05 april 2007 @ 22:02:
omdat dit wiskundig incorrect is...
[...] 1,00005 + 1,000123 = 1,000173
offtopic:
spreken over wiskundige correctheid, en dan zoveel stellen als 1,0 + 1,0 = 1,0 8)7

Misschien dat zoiets werkt, geen idee hoe performant dit zou zijn.
Java:
1
2
3
4
5
6
7
8
9
int getSignificance(double val) {
  int significance = 0;
  double power = 1;
  while ((val * power) != (double)((int)(val * power))) {
    ++significance;
    power *= 10;
  }
  return significance;
}

Ik weet overigens niet zeker of significance hier de correcte term is, maar het idee is duidelijk lijkt me.
edit:
zaakje werkend gemaakt
significant sneller gemaakt... ;)

[ Voor 108% gewijzigd door NetForce1 op 05-04-2007 23:15 . Reden: quote en codevoorbeeld toegevoegd ]

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • _js_
  • Registratie: Oktober 2002
  • Laatst online: 01-12 20:47
Jullie weten dat een double een binair getal is? En wat binair een net afgerond getal is kan decimaal oneindig doorgaan, en andersom.

  • Mischa_NL
  • Registratie: Mei 2004
  • Laatst online: 01-02-2023
_js_ schreef op donderdag 05 april 2007 @ 22:46:
Jullie weten dat een double een binair getal is? En wat binair een net afgerond getal is kan decimaal oneindig doorgaan, en andersom.
een hele computer is binair?

Verwijderd

[quote]NetForce1 schreef op donderdag 05 april 2007 @ 22:12:
[...]


offtopic:
spreken over wiskundige correctheid, en dan zoveel stellen als 1,0 + 1,0 = 1,0 8)7

misschien niet helemaal duidelijk....

1,000223 +/- 0,0000005 != 1,000173

Verwijderd

Mischa_NL schreef op donderdag 05 april 2007 @ 22:49:
[...]

een hele computer is binair?
je double is binair.... en ook decimaal. en octaal. en hexadecimaal.... ongetwijfeld ook pentadecimaal etc...

in de hardware en software op de pc wordt hij weergegeven als binair... afhankelijk van je instelling word hij op je scherm weergegeven als decimaal.

binair/decimaal/etc is enkel de manier van weergeven.

  • Janoz
  • Registratie: Oktober 2000
  • Nu online

Janoz

Moderator Devschuur®

!litemod

binair/decimaal/etc is enkel de manier van weergeven.
Het is niet enkel de manier van weergeven. Binair is ook daadwerkelijk de manier van opslaan. Waarom dit van belang is wordt bij elke fatsoenlijke programmeer opleiding in de datatype/floating point arithmetiek les behandeld, maar is gelukkig ook overal op internet te vinden.

Bijvoorbeeld wikipedia en dan onderandere 'Minimizing the effect of accuracy problems'

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • NetForce1
  • Registratie: November 2001
  • Laatst online: 08:51

NetForce1

(inspiratie == 0) -> true

Ik verwachtte ook tegen floating point problemen aan te lopen bij het maken van de functie. De functie zoals ie er nu staat draait echter prima op Java 1.5 onder Ubuntu. Als je de tussenvariabele power weg-refactored treden wel floating point errors op en kom je in een oneindige loop.

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
in C# kan je in dit soort gevallen inderdaad beter een Decimal gebruiken om de reden dat Janoz en _js_ aanhalen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Verwijderd

rwb schreef op vrijdag 06 april 2007 @ 17:17:
in C# kan je in dit soort gevallen inderdaad beter een Decimal gebruiken om de reden dat Janoz en _js_ aanhalen.
Daar is vorige maand nog een hele interessante post over geweest door een medewerker van MS:

http://blogs.msdn.com/luc...to-represent-numbers.aspx

Die geeft guidelines daarvoor ;) (En raadt dus idd ook decimals aan).
Pagina: 1