Ich möchte in der Lage sein, zwei Variablen ohne die Verwendung einer temporären Variablen in C # auszutauschen. Kann das gemacht werden?
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
// Swap each:
// startAngle becomes: 355.87
// stopAngle becomes: 159.9
Antworten:
Zunächst einmal ist das Austauschen ohne temporäre Variable in einer Sprache als C # eine sehr schlechte Idee .
Zur Beantwortung können Sie diesen Code verwenden:
Probleme beim Abrunden können jedoch auftreten, wenn sich die beiden Zahlen stark unterscheiden. Dies liegt an der Natur von Gleitkommazahlen.
Wenn Sie die temporäre Variable ausblenden möchten, können Sie eine Dienstprogrammmethode verwenden:
public static class Foo { public static void Swap<T> (ref T lhs, ref T rhs) { T temp = lhs; lhs = rhs; rhs = temp; } }
quelle
Der richtige Weg, um zwei Variablen auszutauschen, ist:
decimal tempDecimal = startAngle; startAngle = stopAngle; stopAngle = tempDecimal;
Verwenden Sie mit anderen Worten eine temporäre Variable.
Hier hast du es. Keine cleveren Tricks, keine Betreuer Ihres Codes, die Sie jahrzehntelang verfluchen, keine Einträge in The Daily WTF und kein zu viel Zeitaufwand, um herauszufinden, warum Sie ihn sowieso in einem Vorgang benötigen, da auf der untersten Ebene sogar der Das komplizierteste Sprachmerkmal ist eine Reihe einfacher Operationen.
Nur eine sehr einfache, lesbare, leicht verständliche
t = a; a = b; b = t;
Lösung.Meiner Meinung nach versuchen Entwickler, die versuchen, Tricks zu verwenden, um beispielsweise "Variablen ohne Zeitarbeit zu tauschen" oder "Duffs Gerät", nur zu zeigen, wie klug sie sind (und kläglich scheitern).
Ich vergleiche sie mit denen, die hochkarätige Bücher nur lesen, um auf Partys interessanter zu wirken (im Gegensatz zur Erweiterung Ihres Horizonts).
Lösungen, bei denen Sie addieren und subtrahieren, oder XOR-basierte Lösungen sind weniger lesbar und höchstwahrscheinlich langsamer als eine einfache Lösung mit "temporären Variablen" (Arithmetik / Boolesche Operationen anstelle von einfachen Bewegungen auf Baugruppenebene).
Machen Sie sich und anderen einen Dienst, indem Sie lesbaren Code von guter Qualität schreiben.
Das ist mein Schimpfen. Danke fürs Zuhören :-)
Abgesehen davon bin ich mir ziemlich bewusst, dass dies Ihre spezifische Frage nicht beantwortet (und ich werde mich dafür entschuldigen), aber es gibt viele Präzedenzfälle in SO, in denen Leute gefragt haben, wie man etwas macht, und die richtige Antwort lautet "Nicht tun" Tu es".
quelle
In C # 7 wurden Tupel eingeführt, mit denen zwei Variablen ohne temporäre ausgetauscht werden können:
int a = 10; int b = 2; (a, b) = (b, a);
Dies weist
b
zua
unda
zub
.quelle
Ja, verwenden Sie diesen Code:
stopAngle = Convert.ToDecimal(159.9); startAngle = Convert.ToDecimal(355.87);
Bei beliebigen Werten ist das Problem schwieriger. :-)
quelle
int a = 4, b = 6; a ^= b ^= a ^= b;
Funktioniert für alle Typen, einschließlich Strings und Floats.
quelle
^=
mitstring
oder verwendenfloat
, sodass er nicht mit ihnen kompiliert wird.BenAlabaster zeigte eine praktische Möglichkeit, einen Variablenwechsel durchzuführen, aber die try-catch-Klausel wird nicht benötigt. Dieser Code ist genug.
static void Swap<T>(ref T x, ref T y) { T t = y; y = x; x = t; }
Die Verwendung ist die gleiche wie er gezeigt hat:
float startAngle = 159.9F float stopAngle = 355.87F Swap(ref startAngle, ref stopAngle);
Sie können auch eine Erweiterungsmethode verwenden:
static class SwapExtension { public static T Swap<T>(this T x, ref T y) { T t = y; y = x; return t; } }
Verwenden Sie es so:
float startAngle = 159.9F; float stopAngle = 355.87F; startAngle = startAngle.Swap(ref stopAngle);
In beiden Fällen wird eine temporäre Variable in der Methode verwendet, Sie benötigen jedoch nicht die temporäre Variable, in der Sie den Austausch durchführen.
quelle
Ein binärer XOR-Swap mit einem detaillierten Beispiel:
XOR-Wahrheitstabelle :
a b a^b 0 0 0 0 1 1 1 0 1 1 1 0
Eingang:
a = 4; b = 6;
Schritt 1 : a = a ^ b
a : 0100 b : 0110 a^b: 0010 = 2 = a
Schritt 2 : b = a ^ b
a : 0010 b : 0110 a^b: 0100 = 4 = b
Schritt 3 : a = a ^ b
a : 0010 b : 0100 a^b: 0110 = 6 = a
Ausgabe:
a = 6; b = 4;
quelle
Nicht in C #. Im nativen Code können Sie möglicherweise den Triple-XOR-Swap-Trick verwenden, jedoch nicht in einer typsicheren Hochsprache. (Wie auch immer, ich habe gehört, dass der XOR-Trick tatsächlich langsamer ist als die Verwendung einer temporären Variablen in vielen gängigen CPU-Architekturen.)
Sie sollten nur eine temporäre Variable verwenden. Es gibt keinen Grund, warum Sie keinen verwenden können. Es ist nicht so, dass es nur ein begrenztes Angebot gibt.
quelle
Im Interesse zukünftiger Lernender und der Menschheit übergebe ich diese Korrektur der aktuell ausgewählten Antwort.
Wenn Sie die Verwendung von temporären Variablen vermeiden möchten, gibt es nur zwei sinnvolle Optionen , bei denen zuerst die Leistung und dann die Lesbarkeit berücksichtigt werden.
Swap
Methode. (Absolut beste Leistung neben der Inline-Temperaturvariablen)Interlocked.Exchange
. (5,9-mal langsamer auf meinem Computer, aber dies ist Ihre einzige Option, wenn mehrere Threads diese Variablen gleichzeitig austauschen.)Dinge, die Sie niemals tun sollten:
Decimal
ist kein CPU-Grundelement und führt zu weitaus mehr Code als Sie denken.Da jeder harte Zahlen liebt, finden Sie hier ein Programm, das Ihre Optionen vergleicht. Führen Sie es im Release-Modus von außerhalb von Visual Studio aus, damit
Swap
es inline ist. Ergebnisse auf meinem Computer (Windows 7 64-Bit i5-3470):Inline: 00:00:00.7351931 Call: 00:00:00.7483503 Interlocked: 00:00:04.4076651
Code:
class Program { static void Swap<T>(ref T obj1, ref T obj2) { var temp = obj1; obj1 = obj2; obj2 = temp; } static void Main(string[] args) { var a = new object(); var b = new object(); var s = new Stopwatch(); Swap(ref a, ref b); // JIT the swap method outside the stopwatch s.Restart(); for (var i = 0; i < 500000000; i++) { var temp = a; a = b; b = temp; } s.Stop(); Console.WriteLine("Inline temp: " + s.Elapsed); s.Restart(); for (var i = 0; i < 500000000; i++) { Swap(ref a, ref b); } s.Stop(); Console.WriteLine("Call: " + s.Elapsed); s.Restart(); for (var i = 0; i < 500000000; i++) { b = Interlocked.Exchange(ref a, b); } s.Stop(); Console.WriteLine("Interlocked: " + s.Elapsed); Console.ReadKey(); } }
quelle
0
wird ein Compiler zum Laden in ein Register die Variable mit sich selbst xorieren, weil der Befehl kürzer ist. In einigen seltenen Fällen wird durch die Verwendung weniger Variablen das Verschütten von Registern vermieden. Es ist die Aufgabe des Compilers, aber es ist bedauerlich, dass es keine Sprachunterstützung gibt, um dies effizient zu tun.<veraltet>
Sie können es in 3 Zeilen mit einfacher Mathematik machen - in meinem Beispiel habe ich Multiplikation verwendet, aber eine einfache Addition würde auch funktionieren.
float startAngle = 159.9F; float stopAngle = 355.87F; startAngle = startAngle * stopAngle; stopAngle = startAngle / stopAngle; startAngle = startAngle / stopAngle;
Bearbeiten: Wie in den Kommentaren erwähnt, würde dies nicht funktionieren, wenn y = 0 wäre, da dies einen Fehler beim Teilen durch Null erzeugen würde, den ich nicht berücksichtigt hatte. Die alternativ vorgestellte +/- Lösung wäre also der beste Weg.
</ veraltet>
Um meinen Code sofort verständlich zu halten, würde ich eher so etwas tun. [Denken Sie immer an den armen Kerl, der Ihren Code pflegen muss]:
static bool Swap<T>(ref T x, ref T y) { try { T t = y; y = x; x = t; return true; } catch { return false; } }
Und dann können Sie es in einer Codezeile tun:
float startAngle = 159.9F float stopAngle = 355.87F Swap<float>(ref startAngle, ref stopAngle);
Oder...
MyObject obj1 = new MyObject("object1"); MyObject obj2 = new MyObject("object2"); Swap<MyObject>(ref obj1, ref obj2);
Fertig wie beim Abendessen ... Sie können jetzt jede Art von Objekt übergeben und umschalten ...
quelle
In C # 7:
quelle
Der Vollständigkeit halber hier der binäre XOR-Swap:
int x = 42; int y = 51236; x ^= y; y ^= x; x ^= y;
Dies funktioniert für alle atomaren Objekte / Referenzen, da es sich direkt um die Bytes handelt, erfordert jedoch möglicherweise einen unsicheren Kontext, um Dezimalstellen oder, wenn Sie sich wirklich verdreht fühlen, Zeiger zu bearbeiten. Unter bestimmten Umständen kann es auch langsamer als eine temporäre Variable sein.
quelle
Wenn Sie von using
decimal
zu ändern können , könnendouble
Sie dieInterlocked
Klasse verwenden. Vermutlich ist dies eine gute Möglichkeit, Variablen in Bezug auf die Leistung auszutauschen. Auch etwas besser lesbar als XOR.var startAngle = 159.9d; var stopAngle = 355.87d; stopAngle = Interlocked.Exchange(ref startAngle, stopAngle);
Msdn: Interlocked.Exchange-Methode (Double, Double)
quelle
Mit C # 7 können Sie die Tupeldekonstruktion verwenden, um den gewünschten Austausch in einer Zeile zu erzielen, und es ist klar, was los ist.
decimal startAngle = Convert.ToDecimal(159.9); decimal stopAngle = Convert.ToDecimal(355.87); (startAngle, stopAngle) = (stopAngle, startAngle);
quelle
Passen Sie auf Ihre Umgebung auf!
Dies scheint beispielsweise in ECMAscript nicht zu funktionieren
Aber das tut es
Mein Rat? Nehmen Sie so wenig wie möglich an.
quelle
Der einfache Weg, 2 Zahlen in nur einer Zeile zu tauschen:
zB: a = 1, b = 2
Schritt 1: a = (1 + 2) - (b = 1)
Schritt 2: a = 3-1
=> a = 2 und b = 1
Effizienter Weg ist zu verwenden:
C Programmierung:
(x ^= y), (y ^= x), (x ^= y);
Java:
x = x ^ y ^ (y = x);
Python:
x, y = y, x
Hinweis: Die häufigsten Fehler, die Menschen machen: // Tauschen Sie mit bitweisem XOR (Falsche Lösung in C / C ++)
Quelle: GeeksforGeek
quelle
std::swap(x, y);
.َ
quelle
Für Binärtypen können Sie diesen funky Trick verwenden:
Solange a und b nicht genau dieselbe Variable sind (z. B. Aliase für denselben Speicher), funktioniert es.
quelle
Ich hoffe das könnte helfen ...
using System; public class Program { public static void Main() { int a = 1234; int b = 4321; Console.WriteLine("Before: a {0} and b {1}", a, b); b = b - a; a = a + b; b = a - b; Console.WriteLine("After: a {0} and b {1}", a, b); } }
quelle
Mit Tupeln
decimal startAngle = Convert.ToDecimal(159.9); decimal stopAngle = Convert.ToDecimal(355.87); (startAngle, stopAngle) = (stopAngle, startAngle);
quelle
quelle
Wir können das tun, indem wir einen einfachen Trick machen
a = 20; b = 30; a = a+b; // add both the number now a has value 50 b = a-b; // here we are extracting one number from the sum by sub a = a-b; // the number so obtained in above help us to fetch the alternate number from sum System.out.print("swapped numbers are a = "+ a+"b = "+ b);
quelle
Wenn Sie 2 Zeichenfolgenvariablen austauschen möchten:
Eine Hilfsmethode entsprechend:
public static class Foo { public static void SwapString (ref string a, ref string b) { a = (a+b).Substring((b=a).Length); } }
Verwendung wäre dann:
string a="Test 1"; string b="Test 2"; Foo.SwapString(a, b);
quelle
Hier ein weiterer Ansatz in einer Zeile:
decimal a = 159.9m; decimal b = 355.87m; a = b + (b = a) - b;
quelle
Hier ist ein anderer Prozess, um zwei Variablen auszutauschen
//process one a=b+a; b=a-b; a=a-b; printf("a= %d b= %d",a,b); //process two a=5; b=10; a=a+b-(b=a); printf("\na= %d b= %d",a,b); //process three a=5; b=10; a=a^b; b=a^b; a=b^a; printf("\na= %d b= %d",a,b); //process four a=5; b=10; a=b-~a-1; b=a+~b+1; a=a+~b+1; printf("\na= %d b= %d",a,b);
quelle
var a = 15; var b = -214; a = b | !(b = a);
Das funktioniert super.
quelle
Sehr einfacher Code zum Austauschen von zwei Variablen:
static void Main(string[] args) { Console.WriteLine("Prof.Owais ahmed"); Console.WriteLine("Swapping two variables"); Console.WriteLine("Enter your first number "); int x = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("Enter your first number "); int y = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("your vlaue of x is="+x+"\nyour value of y is="+y); int z = x; x = y; y = z; Console.WriteLine("after Swapping value of x is="+x+"/nyour value of y is="+y); Console.ReadLine(); }
quelle
z
als temporäre Variable zählt.Sie können den folgenden Code ausprobieren. Es ist viel besser als der andere Code.
quelle