2016-05-06 11 views
2

Ich habe eine Dezimalstelle namens "Summe" und sein Wert ist 5824088.999120m, aber wenn ich versuche, es auf 3 Dezimalstellen runden, bekomme ich 5824088.998m statt 5824088.999m. Es dekrementiert anstatt 5824088.999m zu verlassen.Dezimal nicht richtig gerundet

Warum ist es? Hier ist mein Code:

List<decimal> quantityList = QuantityList(); 
List<decimal> priceList = PriceList(); 

decimal destination = 5824088.999M; 
decimal sum = 0M; 
bool lifesaver = false; 

for (int x = 0; x < priceList.Count; x++) 
{ 
    sum = 0M; 
    for (int i = 0; i < 3500; i++) 
    { 
     priceList[x] += 0.001M; 
     sum = 0M; 
     for (int y = 0; y < priceList.Count; y++) 
     { 
      decimal multipleProduct = priceList[y] * quantityList[y]; 
      sum = sum + multipleProduct; 
      Console.WriteLine(priceList[y] + " " + quantityList[y]); 

      sum = Math.Round(sum, 3); 
      Console.WriteLine("Sum: " + sum); 
      Console.ReadKey(); 
      Console.WriteLine(); 
     } 

     if (sum == destination) 
     { 
      Console.WriteLine("The new number is " + priceList[x] + " and it is the {0} element!", x); 
      lifesaver = true; 
      break; 
     } 
     else if (sum > destination) 
     { 
      Console.WriteLine("Limit exceeded!"); 
     } 

     if (i == 3499) 
     { 
      priceList[x] -= 3.500M; 
     } 
     if (lifesaver == true) 
     { 
      break; 
     } 
    }//Second for loop 

    if (lifesaver == true) 
    { 
     break; 
    } 
}//Main for loop 

Die Listen sind in einer anderen Methode.

Antwort

3

Es scheint, dass Sie runden up Fehler Akkumulation und damit die Gesamt ist falsch:

for (int y = 0; y < priceList.Count; y++) { 
    ... 
    sum = Math.Round(sum, 3); // <- this accumulates round up errors 
    ... 
    } 

vorstellen, dass die priceList enthält

priceList = new List<Decimal>() { 
    1.0004M, 1.0004M, 1.0004M}; 

während quantityList alle je 1 sind; die sum wird

1.000M, 2.000M, 3.000M 

sein, während die tatsächliche Gesamt

Math.Round(1.0004M + 1.0004M + 1.0004M, 3) 

3.001M ist. Mögliche Abhilfe rundet nicht vorzeitig up:

for (int y = 0; y < priceList.Count; y++) { 
     ... 
     //DONE: comment out this: no premature rounding (within the loop) 
     // sum = Math.Round(sum, 3); 
     //DONE: but format out when printing out 
     Console.WriteLine("Sum: {0:F3}", sum); 
     ... 
    } 

    // round up (if you want) after the loop 
    sum = Math.Round(sum, 3); 
+0

@Reza Taibur: durch * Entfernen/Auskommentieren * 'Summe = Math.Round (Summe, 3);' - nur nicht * innerhalb der Schleife * (vorzeitig) aufrunden, summieren nur Werte und formatieren sie beim Ausdrucken . Wenn Sie aufrunden wollen, tun Sie es * nach * der Schleife –

+0

Danke! Nicht in der Schleife zusammen arbeiten! –

0

Sie sollten in MidpointRounding (https://msdn.microsoft.com/en-us/library/system.midpointrounding(v=vs.110).aspx) suchen und diese zu Ihrer Math.Round-Funktion hinzufügen. So: sum = Math.Round(sum, 3, MidpointRounding.ToEven);, die andere Option, die Sie haben, ist MidpointRounding.AwayFromZero, die für Sie besser sein könnte.

+1

Nun, ich bin mir sicher, dass die Verwendung von AwayFromZero ToEven in einer anderen Weise runden. Wenn Sie es versucht haben, warum sagen Sie uns nicht, dass Sie es getan haben und was die Ergebnisse waren. Sie können nicht einfach erwarten, dass wir alle wissen, was Sie versucht haben und was nicht. "Funktioniert nicht, ich habe es schon ausprobiert.", Ist nicht wirklich eine anständige Antwort auf eine Antwort, würde ich streiten. –

0

es wegen der Math.Round Methode.

Hier ist das MSDN documentation.

Dieses Verfahren entspricht die Runde zu rufen (dezimal, Int32, MidpointRounding) Methode mit einem Argument des Modus MidpointRounding.ToEven.When d genau auf halber Strecke zwischen zwei gerundeten Werte ist, ist das Ergebnis der gerundete Wert, der ein HAS gerade Ziffer in der rechten Dezimalstelle. Wenn beispielsweise auf zwei Dezimalstellen gerundet wird, wird der Wert 2,345 2,34 und der Wert 2,355 wird 2,36. Dieser Prozess ist bekannt als Rundung in Richtung der geraden oder Banker-Runden. Es minimiert Rundungsfehler, die sich aus der konsistenten Rundung eines Mittelpunktwerts in einer einzigen Richtung ergeben.

sollten Sie versuchen, die Math.Round(decimal, int32, System.MidpointRounding), die here

Versuchen Sie nannte es mit dem MidPointRounding Enum AwayFromZero Wert gefunden werden kann.

Beispiel:

decimal d = 5824088.999120M; 
decimal rounded = Math.Round(d, 3, System.MidpointRounding.AwayFromZero); 
Console.WriteLine(rounded.ToString()); 

Logs 5824088.999

Aus Bemerkungen:

Die Dezimalstellen Parameter gibt die Anzahl der signifikanten Dezimalstellen in der Rückgabewert und reicht von 0 bis 28. Wenn Dezimalzahlen ist Null, eine Ganzzahl wird zurückgegeben.

In einem Mittelpunktwert ist der Wert nach der niedrigstwertigen Stelle im Ergebnis genau die Hälfte zwischen zwei Zahlen. Beispielsweise ist 3,47500 ein Mittelpunktwert, wenn er auf zwei Dezimalstellen gerundet werden soll, und 7,500 ist ein Mittelpunktwert, wenn er auf eine ganze Zahl gerundet werden soll. In diesen Fällen kann der nächste Wert nicht ohne eine Rundungskonvention identifiziert werden, die durch das mode-Argument angegeben wird. Die Methode Round (Decimal, Int32, MidpointRounding) unterstützt zwei Rundungskonventionen für die Behandlung von Mittelpunktwerten.

Rundung von Null. Mittelpunktwerte werden auf die nächste von Null entfernte Zahl gerundet. Zum Beispiel 3,75 Runden auf 3,8, 3,85 Runden auf 3,9, -3,75 Runden auf -3,8 und -3,85 Runden auf -3,9. Diese Form der Rundung wird durch das MidpointRounding.AwayFromZero-Enumerationselement dargestellt. Die Rundung von Null ist die bekannteste Form der Rundung.

Rundung auf gerade oder Banker-Rundung Mittelpunktwerte werden auf die nächste gerade Zahl gerundet. Zum Beispiel runden sowohl 3,75 als auch 3,85 auf 3,8 und beide -3,75 und -3,85 runden auf -3,8 ab. Diese Form der Rundung wird durch das Aufzählungselement MidpointRounding.ToEven dargestellt. Die Rundung auf das nächste ist die Standardform der Rundung, die im Finanz- und Statistikbetrieb verwendet wird. Es entspricht dem IEEE-Standard 754, Abschnitt 4. Wenn es in mehreren Rundungsoperationen verwendet wird, reduziert es den Rundungsfehler, der durch konsistente Rundung von Mittelpunktwerten in einer einzigen Richtung verursacht wird. In einigen Fällen kann dieser Rundungsfehler erheblich sein.

Überprüfen Sie diese .NET fiddle auch. Wenn Sie es ausführen, sehen Sie genau Ihren erwarteten Wert 5824088.999

+0

Ich brauche den genauen Wert der Summe nicht .000 am Ende –

+0

@RezaTaibur Ich fürchte, ich kann nicht verstehen, was Sie brauchen. Können Sie bitte klarstellen, was genau Sie in Ihrer Frage brauchen, damit wir Ihnen helfen können? – gdyrrahitis

+0

Vielen Dank, aber ich habe bereits die Antwort (siehe Dmytri Bychenkos Antwort) –