it-swarm.com.de

C #: Wie kann ich einfache Berechnungen mit Rundungen für ganze Zahlen durchführen?

ich möchte das Ergebnis einer auf die nächste ganze Zahl gerundeten Gleichung. z.B.

137 * (3/4) = 103

Betrachten Sie den folgenden falschen Code.

int width1 = 4;
int height1 = 3;

int width2 = 137;
int height2 = width2 * (height1 / width1);

Was ist der richtige Weg, um "Integer" -Mathematik in C # durchzuführen?

Muss ich wirklich tun:

int height2 = (int)Math.Round(
      (float)width2 * ((float)height1 / (float)width1)
   );
19
Ian Boyd

Wie oben gesagt, sollten Sie die Multiplikation vor der Division durchführen. Sie könnten Ihren Ausdruck trotzdem schreiben, indem Sie nur den Divisor werfen:

int height2 = (int)Math.Round(width2 * (height1 / (float)width1));
16
Aaron
int height2 = (width2 * height1) / width1;
3

Mache zuerst die Multiplikation (solange sie nicht überlaufen) und dann die Division.

3/4 == 0 in Ganzzahl-Mathematik (Ganzzahl-Mathematik rundet die Division nicht, sie schneidet ab).

Wenn Sie wirklich eine Rundung benötigen, müssen Sie entweder mit einem festen Punkt, einem Fließpunkt oder mit dem Modul arbeiten.

3
plinth

Ich denke, das ist der eleganteste Weg, dies zu tun:

Math.round(myinteger * 0.75);

Die Verwendung von 0,75 anstelle von 3/4 wird implizit in ein Double/Float umgewandelt. Warum werden nicht die Standardfunktionen verwendet, die dafür bereitgestellt werden?

2
Ruben

Ich bin gerade über diese Frage gestolpert. Aarons Antwort scheint mir fast richtig zu sein. Ich bin mir jedoch sehr sicher, dass Sie die Mittelpunktsbestimmung angeben müssen, wenn Ihr Problem ein Problem der "realen Welt" ist. Also meine Antwort, basierend auf Aarons Code

int height2 = (int)Math.Round(width2 * (height1 / (float)width1),MidpointRounding.AwayFromZero);

Um den Unterschied zu sehen, führen Sie diesen Code in der Konsole aus

    Console.WriteLine((int)Math.Round(0.5));
    Console.WriteLine((int)Math.Round(1.5));
    Console.WriteLine((int)Math.Round(2.5));
    Console.WriteLine((int)Math.Round(3.5));
    Console.WriteLine((int)Math.Round(0.5, MidpointRounding.AwayFromZero));
    Console.WriteLine((int)Math.Round(1.5, MidpointRounding.AwayFromZero));
    Console.WriteLine((int)Math.Round(2.5, MidpointRounding.AwayFromZero));
    Console.WriteLine((int)Math.Round(3.5, MidpointRounding.AwayFromZero));
    Console.ReadLine();

Einzelheiten finden Sie in this article.

1
Pianoman

Ich werde den falschen Code korrigieren, indem ich null Codezeilen hinzufüge:

float width1 = 4;
float height1 = 3;

float width2 = 137;
float height2 = width2 * (height1 / width1);

Sie sollten Floats für Variablen verwenden, die möglicherweise Dezimalzahlen enthalten können. Dies beinhaltet Höhen, die aus Verhältnissen berechnet werden. Sie können später immer in int konvertieren, wenn dies ein Problem ist.

1
andrewrk

Nie in Float gießen, es ist sogar weniger genau als eine 32-Bit-Ganzzahl. Wenn Sie Fließkomma verwenden möchten, verwenden Sie immer double anstelle von float.

1
rwallace

Sechs Jahre später (gerundet), hier ist mein Beitrag - ein kleiner Trick, den ich vor langer Zeit gelernt habe, und bin überrascht, dass hier niemand anders erwähnt hat.

Die Idee ist, eine Rundung durchzuführen, indem der Zähler vor der Division die Hälfte des Divisors hinzugefügt wird. 

    int height2 = (width2 * height1 + width1 / 2) / width1;

In der Realität würde ich nicht unbedingt empfehlen, dies in Fällen wie den OPs zu tun, bei denen der Divisor eine Variable ist. Stattdessen ist es möglicherweise besser, Math.Round () zu verwenden, da dies viel einfacher zu verstehen ist.

Aber wenn der Divisor eine Konstante ist, benutze ich diesen Trick. Also statt 

    int height2 = width2 * height1 / 4;  // No rounding

Ich würde verwenden

    int height2 = (width2 * height1 + 2) / 4;

Hier ist ein typischeres Beispiel

  private static Size ResizeWithPercentage(Size oldSize, int resizePercentage)
  {
     return new Size((oldSize.Width * resizePercentage + 50) / 100, 
                     (oldSize.Height * resizePercentage + 50) / 100);
  }

Eine andere Möglichkeit besteht darin, diesen Trick mit der von dongilmore und supercat genannten Idee zu kombinieren, indem Sie anstelle der Angabe einer Division durch zwei sowohl den Zähler als auch den Nenner mit zwei multiplizieren.

    int height2 = (width2 * height1 * 2 + width1) / (width1 * 2);

Dies gibt bessere Antworten in Fällen, in denen der Divisor eine ungerade Zahl ist oder sein kann.

1
RenniePet
int height2 = ((width2 * height1 * 10) + 5) / (width1 * 10);

Stellen Sie vor jeder Ganzzahldivision sicher, dass der Divisor nicht Null ist. Beachten Sie auch, dass dies einen positiven Quotienten voraussetzt. Bei einem negativen Wert muss die Rundung -5 sein, nicht +5. 

0
dongilmore

Konvertierungen konvertieren immer so:

int height2 = Convert.ToInt32(width2 * height1 / (double)width1);
0
Tod

Ein vernünftig wirksamer Ansatz, wenn die letzte Division durch eine gerade Zahl erfolgt und das Ergebnis immer positiv ist, ist die Division dieses Wertes durch die Hälfte, die Addition von Eins und die Division durch zwei. Wenn das Ergebnis negativ sein kann, sollten Sie, wenn möglich, einen Betrag addieren, der alles positiv macht, die Berechnung durchführen und anschließend einen entsprechenden Betrag abziehen.

Wenn die letzte Division eine ungerade Zahl ist, multiplizieren Sie sowohl Zähler als auch Nenner mit 2 und gehen Sie dann wie oben beschrieben vor. Berechnen Sie zum Beispiel einen gerundeten * 5/7 (a*10+1)>>1. Es ist zu beachten, dass Sie Ihre Werte möglicherweise auf einen größeren numerischen Typ erweitern müssen, um einen Überlauf zu vermeiden. Wenn dies nicht möglich ist, unterteilen Sie die Unterteilung in Teile. Um zum Beispiel * 14/15 zu berechnen, können Sie ((a * 4/3 * 7)/5 + 1)/2 berechnen. Diese Berechnung kann immer noch überlaufen, wenn a zu groß ist. Der zulässige Bereich ist jedoch dreimal so groß, als wäre er ausgewertet worden, ohne dass die Division vor der anderen Division durch 3 dividiert wurde. Beachten Sie, dass die Unterteilung der Operation die Rundung etwas weniger genau macht, aber für viele Zwecke immer noch nahe genug ist.

0
supercat

Um auf Jefferys Nachricht einzugehen, da Sie im Allgemeinen eine bessere Chance haben, benötigte Dezimalstellen abzuschneiden als eine 32-Bit-Ganzzahl überlaufen zu lassen (und da Multiplikation und Division kommutativ sind), sollten Sie im Allgemeinen die Multiplikation vor der Division durchführen.

0
James Curran