2016-08-01 34 views
3

Es gibt bereits Lösungen für dieses Problem für kleine Zahlen:Differenz zwischen zwei großen Zahlen C#

I Ich fasse die Antwort auf alle zusammen:

Math.Abs(a - b) 

Das Problem ist , wenn die Zahlen groß sind dies gibt die falsche Antwort (mittels eines Überlaufs). Schlimmer noch, wenn (a - b) = Int32.MinValue dann Math.Abs mit einer Ausnahme abstürzt (weil Int32.MaxValue = Int32.MinValue - 1). Seine spezifische Natur führt zu schwer zu reproduzierenden Fehlern.

Vielleicht fehlt mir eine wohlbekannte Bibliotheksfunktion, aber gibt es irgendeine Möglichkeit, den Unterschied sicher zu bestimmen?

+6

BigInteger - https://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx –

+5

Was ist mit der Konvertierung zu einem langen (Int64) und dann den Unterschied zu finden ? – Igor

+0

Sind a und b Int32 oder Int64? – Liam

Antwort

0

Die BigInteger wurde in .Net 4.0 eingeführt.

Es gibt einige Open-Source-Implementierungen, die in niedrigeren Versionen des .Net-Frameworks verfügbar sind. Sie sollten jedoch den Standard verwenden.

Wenn die Math.Abs immer noch Trauer gibt, können Sie die Funktion selbst implementieren; Wenn die Zahl negativ ist (a - b < 0), trimmen Sie einfach das negative Symbol, so dass es nicht vorzeichenbehaftet ist.

Haben Sie auch versucht, Doubles zu verwenden? Sie enthalten viel größere Werte.

2

Wie bereits von anderen vorgeschlagen, verwenden BigInteger wie in System.Numerics definiert (Sie werden den Namespace in Visual Studio enthalten müssen) Dann können Sie einfach tun:

BigInteger a = new BigInteger(); 
BigInteger b = new BigInteger(); 
// Assign values to a and b somewhere in here... 
// Then just use included BigInteger.Abs method 
BigInteger result = BigInteger.Abs(a - b); 

Jeremy Thompson Antwort ist immer noch gültig Beachten Sie jedoch, dass der BigInteger-Namespace eine Absolutwertmethode enthält, sodass keine spezielle Logik erforderlich ist. Außerdem erwartet Math.Abs ​​eine Dezimalzahl, sodass Sie sich Sorgen machen, wenn Sie versuchen, einen BigInteger zu übergeben.

Bedenken Sie, dass die Verwendung von BigIntegers mit Einschränkungen verbunden ist. Wenn Sie eine lächerlich große Zahl haben, wird C# versuchen, Speicher für sie zuzuweisen, und Sie können auf Speicherausnahmen stoßen. Auf der anderen Seite sind BigIntegers großartig, weil die Menge an Speicher, die ihnen zugewiesen ist, dynamisch verändert wird, wenn die Anzahl größer wird.

Schauen Sie sich die Microsoft Referenz hier für weitere Informationen: https://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx

1

Die Frage ist, wie kann man den Unterschied zwischen zwei großen Zahlen halten wollen? Wenn Sie beispielsweise den Unterschied zwischen zwei vorzeichenbehafteten langen (64-Bit-) ganzen Zahlen berechnen und der Unterschied nicht in eine vorzeichenbehaftete lange Ganzzahl passt, wie beabsichtigen Sie, sie zu speichern?

long a = +(1 << 62) + 1000; 
long b = -(1 << 62); 

long dif = a - b; // Overflow, bit truncation 

Der Unterschied zwischen a und b breiter als 64 Bits, so dass, wenn es in eine lange ganze Zahl gespeichert ist, seine höherwertigen Bits werden abgeschnitten, und Sie erhalten einen seltsamen Wert für dif.

Mit anderen Worten, Sie können nicht alle möglichen Differenzen zwischen vorzeichenbehafteten ganzzahligen Werten einer bestimmten Breite in einer vorzeichenbehafteten Ganzzahl gleicher Breite speichern. (Sie können nur die Hälfte aller möglichen Werte speichern; die andere Hälfte erfordert ein zusätzliches Bit.)

Sie können entweder einen breiteren Typ verwenden, um den Unterschied zu halten (was Ihnen nicht hilft, wenn Sie Verwenden Sie bereits den breitesten Ganzzahlentyp long oder verwenden Sie einen anderen arithmetischen Typ. Wenn Sie mindestens 64 signierte Bits der Genauigkeit benötigen, müssen Sie wahrscheinlich BigInteger verwenden.

0

Hier ist eine Alternative, die für Sie interessant sein könnte, aber sehr innerhalb der Grenzen einer bestimmten int-Größe liegt. Dieses Beispiel verwendet Int32 und verwendet bitweise Operatoren, um die Differenz und dann den absoluten Wert zu erreichen. Diese Implementierung toleriert Ihr Szenario, wobei a - b dem min int-Wert entspricht, und gibt natürlich den min int-Wert zurück (nicht viel mehr, was Sie tun können, ohne Dinge auf einen größeren Datentyp zu übertragen). Ich glaube nicht, das so gut ist, eine Antwort als BigInteger verwenden, aber es macht Spaß mit, wenn nichts zu spielen, sonst:

static int diff(int a, int b) 
    { 
     int xorResult = (a^b); 
     int diff = (a & xorResult) - (b & xorResult); 
     return (diff + (diff >> 31))^(diff >> 31); 
    } 

Hier sind einige Fälle, ich lief durch das Verhalten zu spielen:

 Console.WriteLine(diff(13, 14)); // 1 
     Console.WriteLine(diff(11, 9)); // 2 
     Console.WriteLine(diff(5002000, 2346728)); // 2655272 
     Console.WriteLine(diff(int.MinValue, 0)); // Should be 2147483648, but int data type can't go that large. Actual result will be -2147483648.