Gå til innhold

Anbefalte innlegg

Hei,

 

Har støtt på noe av det særeste. Jeg har en variabel som er av typen double. Den sammenligner jeg mot en annen variabel som er en streng (som parses). Ved sammenligning får jeg opp at disse ikke er like (selvom de er det).

 


Boolean svar = false;
double beregning = 0;
try
{
               beregning = double.Parse(kunde[5]) + double.Parse(kunde[6]) -                 double.Parse(kunde[8]) + double.Parse(kunde[17]);
}
catch
{
         logg.Write("[ ] Feil ved parsing av tall");
}
                 if (beregning == double.Parse(kunde[9]))
                   {
                       svar = true;
                   }//endif
                   else
                   {
 logg.Write(beregning.ToString()+" ikke lik "+ double.Parse(kunde9]));                        
                   }
      
          
           logg.Write("[ ] \t Kontosammendrag kontrollert");
           logg.Write(svar.ToString());
           return svar;

 

resultatet i loggen er dette:

 

...

8824,97 ikke lik 8824,97

...

 

Legg også merke til siste if setningen. Hvis jeg endrer beregning til dette:

 

double.parse(beregning.ToString()) //altså jeg gjør double->streng->double

 

dvs

 

if(double.Parse(beregning.ToString()) == double.Parse(kunde[9]))

 

Så går det?! ?-Men hvorfor i allverden ??

 

Victurus!

 

*edit : fjernet litt kode får å få det oversiktlig

Endret av victurus
Lenke til kommentar
Videoannonse
Annonse

har nå sittet og fundert mye på dette. Sjekk denne koden:

  double test = 8824.97;
           double test2 = 0 + 8638.4500000000000 + 220.2900000000000 + 0 - 33.7700000000000 - 0 - 0;


           if (test == test2)
           {
               Console.WriteLine("OK!");
           }

 

Denne går jaggu ikke... :ohmy:

 

Victurus!

Lenke til kommentar

decimal test = 8824.97M;
decimal test2 = 0M + 8638.4500000000000M + 220.2900000000000M + 0M - 33.7700000000000M - 0M - 0M;

if (test.Equals(test2))
{
   Response.Write("OK!");
}
else if (test < test2)
{
   Response.Write(test.ToString() + " er mindre enn " + test2.ToString());
}
else if (test > test2)
{
   Response.Write(test.ToString() + " er større enn " + test2.ToString());
}
else
{
   Response.Write(test.ToString() + " er ikke lik " + test2.ToString());
}

 

Resultat: OK!

 

Endret til decimal i stedet for double, og da funka det.

Lenke til kommentar

Dette kan ha noe med at float og double er ganske unøyaktige, når man gjør om en string til double, vil den gjøre om til den verdie nærmest som passer, altså kan man få litt forskjellige resultater hver gang.

IEEE sin flyttall, 80-bit, er laget for å rette litt på dette, men blir ikke brukt av noen programmeringsspråk jeg kjenner, bortsett fra assembly da. decimal tar det enda litt lenger.

Derfor kan det fungere i decimal, men ikke i double eller float, avhenger av presisjonen din.

Lenke til kommentar

Takk for respons! Du har rett, det fungerer med decimal. -Men synes dog at det er rart at double tryner så hardt, på såpass små tall.

 

ta dette eks.

 

double test6 = 1823.96+7001.01;

double test7 = 8824.97;

 

Går ikke.. men endrer jeg test6 til: 7823.96+1001.01 så går det.. Men jeg får endre alt i koden til decimal, så ting fungerer hvertfall. Takk manfred :)

 

 

 

Victurus!

Lenke til kommentar

Så langt jeg kunne lese så har nok GeirGrusom rett her. Presisjonen på en double eller en float er ikke nødvendigvis den største. Mulig du kunne styret litt frem og tilbake med diverse funksjoner i System.Math, men jeg synes liksom det var hakket enklere å da bare bruke decimal i stedet.

Lenke til kommentar
Dette kan ha noe med at float og double er ganske unøyaktige, når man gjør om en string til double, vil den gjøre om til den verdie nærmest som passer, altså kan man få litt forskjellige resultater hver gang.

IEEE sin flyttall, 80-bit, er laget for å rette litt på dette, men blir ikke brukt av noen programmeringsspråk jeg kjenner, bortsett fra assembly da. decimal tar det enda litt lenger.

Derfor kan det fungere i decimal, men ikke i double eller float, avhenger av presisjonen din.

 

Men det jeg stusser på er hvordan den kan summere ut alt og gi svaret med like mange siffer men samtidig påstå at dem ikke er like?

 

Victurus!

Lenke til kommentar

Dette er et problem i alle språk. F.eks.:

 

float f1 = 0.1;

float f2 = 0.1;

 

Her vil man anta at f1 == f2, men det er altså ikke nødvendig vis tilfellet pga. grunner som det er skrevet store avhandlinger om.

 

Ihvertfall, det man ofte gjør når man skal sammenligne to flyttall er å si hvor store forskjeller man kan godta og fortsatt si at tallet er likt.

 

eks.

 

float f1 = 0.001

float f2 = 0.001

 

if( f2 - f1 < 0.0001 || f1 - f2 < 0.0001 )

tallene er tilnærmet like

Lenke til kommentar

jeg skrev en helper klasse for dette

 

Klikk for å se/fjerne innholdet nedenfor
	/// <summary>
/// DoubleCompare is a helper class to compare double precisiion floating point values.
/// It contains a tolerance field wich contains the precision of tolerence.
/// This is only applied to the Equals functions == and !=
/// FloatCompare can be on either side of the comparison.
/// </summary>
/// <example>
/// if(new DoubleCompare(128.021312f) == double.Parse("128.021312"))
///   MessageBox.Show("Equals!");
/// </example>
public struct DoubleCompare
{
 private double m_tolerence;
 private double m_value;

 public double Tolerence
 {
 	get { return m_tolerence; }
 	set { m_tolerence = value; }
 }

 public override int GetHashCode()
 {
 	return m_value.GetHashCode() ^ m_tolerence.GetHashCode();
 }

 public double Value
 {
 	get { return m_value; }
 	set { m_value = value; }
 }

 public DoubleCompare(double value)
 {
 	m_value = value;
 	m_tolerence = 0.0001f;
 }

 public DoubleCompare(double value, double tolerance)
 {
 	m_value = value;
 	m_tolerence = tolerance;
 }

 public override bool Equals(object obj)
 {
 	if (obj is DoubleCompare)
 	{
   return (m_value - ((DoubleCompare)obj).m_value) < m_tolerence;
 	}
 	else if (obj is double)
 	{
   return m_value - (double)obj < m_tolerence;
 	}
 	return false;
 }

 public static bool operator ==(DoubleCompare a, DoubleCompare b)
 {
 	return (a.m_value - b.m_value) < a.m_tolerence;
 }

 public static bool operator ==(DoubleCompare a, double b)
 {
 	return (a.m_value - b) < a.m_tolerence;
 }
 public static bool operator ==(double a, DoubleCompare b)
 {
 	return (a - b.m_value) < b.m_tolerence;
 }


 public static bool operator !=(DoubleCompare a, DoubleCompare b)
 {
 	return !((a.m_value - b.m_value) < a.m_tolerence);
 }

 public static bool operator !=(DoubleCompare a, double b)
 {
 	return !((a.m_value - b) < a.m_tolerence);
 }

 public static bool operator !=(double a, DoubleCompare b)
 {
 	return !((a - b.m_value) < b.m_tolerence);
 }

 public static implicit operator float(DoubleCompare a)
 {
 	return (float)a.m_value;
 }

 public static implicit operator double(DoubleCompare a)
 {
 	return a.m_value;
 }

 public static explicit operator int(DoubleCompare a)
 {
 	return (int)a.m_value;
 }

 public override string ToString()
 {
 	return m_value.ToString();
 }

 public string ToString(IFormatProvider provider)
 {
 	return m_value.ToString(provider);
 }

 public string ToString(string format)
 {
 	return m_value.ToString(format);
 }

 public string ToString(string format, IFormatProvider provider)
 {
 	return m_value.ToString(format, provider);
 }


}

Lenke til kommentar

Hva med å bruke Money klassen?

 

Edit: Nevermind, ser at den ikke finnes. Blandet nok med SQL Server. Merkelig at ikke .NET har noe tilsvarende.

 

Når jeg har jobbet med økonomi så har jeg alltid lagret tallene som en integer. Bare laget en regel på at de to siste sifferene er øre. Eks. 1122 = 11,22 kr

 

 

http://www.michaelbrumm.com/money.html

Endret av alftore
Lenke til kommentar

Decimal erstatter Money.

Edit: Visual Basic 6.0 støttet en datatype som het Currency, men etter det jeg har forstått, er det ingen reell forskjell mellom Currency og Decimal

 

Decimal er 128-bit, som skal være nok til å behandle alle verdens statsbudsjett kombinert.

 

edit2: etter nærmere gjennomgang, er Money datatypen til SQL Server også 128-bit, så da er det ingen tekniske forskjeller mellom dem.

Endret av GeirGrusom
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...