Frage

Ich möchte in der Lage sein, zwei Variablen ohne Verwendung einer temporären Variablen in C # zu tauschen. Kann dies geschehen?

decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);

// Swap each:
//   startAngle becomes: 355.87
//   stopAngle becomes: 159.9
War es hilfreich?

Lösung

Zunächst einmal in einer Sprache wie C #, ohne eine temporäre Variable Swapping ist eine sehr schlechte Idee .

Aber im Interesse der Antwort, können Sie diesen Code verwenden:

startAngle = startAngle + stopAngle;
stopAngle = startAngle - stopAngle;
startAngle = startAngle - stopAngle;

Probleme können jedoch mit Abrundung auftreten, wenn die beiden Zahlen weitgehend unterscheiden. Dies ist aufgrund der Art von Gleitkommazahlen.

Wenn Sie die temporären Variable ausblenden mögen, können Sie eine Dienstprogramm-Methode verwenden:

public static class Foo {

    public static void Swap<T> (ref T lhs, ref T rhs) {
        T temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
}

Andere Tipps

Die rechts Art und Weise zwei Variablen zu tauschen ist:

decimal tempDecimal = startAngle;
startAngle = stopAngle;
stopAngle = tempDecimal;

Mit anderen Worten: eine temporäre Variable verwenden.

Da haben Sie es. Keine cleveren Tricks, keine Maintainer des Codes Sie seit Jahrzehnten Fluchen keine Einträge kommen, um rel="noreferrer"> und keine Ausgaben zu viel Zeit, um herauszufinden, warum Sie es in einem Arbeitsgang benötigt sowieso da, auf der untersten Ebene, auch die komplizierte Sprache-Funktion ist eine Reihe von einfachen Operationen.

Nur eine sehr einfache, gut lesbare, leicht zu verstehen, t = a; a = b; b = t; Lösung.

Meiner Meinung nach, Entwickler, die versuchen, Tricks zu verwenden, zum Beispiel, „Swap-Variablen ohne eine temporäre Verwendung“ oder „Duff Gerät“ versuchen, nur um zu zeigen, wie klug sie sind (und kläglich scheitert).

Ich vergleiche sie zu denen, die ausschließlich zum Zweck der scheinbaren interessanteren auf Partys highbrow Bücher zu lesen (im Gegensatz zu Ihrem Horizont erweitern).

Lösungen, wo Sie addieren und subtrahieren, oder die XOR-basiert sind, sind weniger lesbar und höchstwahrscheinlich langsamer als eine einfache „temp Variable“ Lösung (Arithmetik / boolean-ops statt Ebene bewegt sich auf einer Montageebene).

Tun Sie sich selbst und andere, ein Service von guter Qualität lesbaren Code zu schreiben.

Das ist mein rant. Danke fürs Zuhören: -)

Als beiseite, ich bin ganz bewusst nicht Ihre Frage beantwortet (und ich werde dafür entschuldigen), aber es gibt viel Präzedenzfall auf SO, wo Leute haben gefragt, wie etwas zu tun und ist die richtige Antwort " tun sie es nicht“.

Ja, verwenden Sie diesen Code ein:

stopAngle = Convert.ToDecimal(159.9);
startAngle = Convert.ToDecimal(355.87);

Das Problem ist schwieriger für beliebige Werte. : -)

C # 7 eingeführt Tupel die zwei Variablen ohne temporäre ermöglicht Swapping:

int a = 10;
int b = 2;
(a, b) = (b, a);

Dies weist b a und a b.

int a = 4, b = 6;
a ^= b ^= a ^= b;

Funktioniert für alle Arten einschließlich Saiten und schwimmt.

BenAlabaster zeigte eine praktische Art und Weise einen variablen Schalter zu tun, aber die Try-catch-Klausel ist nicht erforderlich. Dieser Code ist genug.

static void Swap<T>(ref T x, ref T y)
{
     T t = y;
     y = x;
     x = t;
}

Die Verwendung ist das gleiche, wie er gezeigt:

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 wie folgt aus:

float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle.Swap(ref stopAngle);

Beide Wege verwendet eine temporäre Variable in der Methode, aber Sie haben nicht die temporäre Variable benötigen, wo Sie den Austausch tun.

Ein binärer XOR-Swap mit einem ausführlichen Beispiel:

XOR Wahrheitstabelle :

a b a^b
0 0  0
0 1  1
1 0  1
1 1  0

Input:

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

Ausgang:

a = 6;
b = 4;

Nicht in C #. In nativen Code könnten Sie in der Lage sein, den Triple-XOR-Swap-Trick zu verwenden, aber nicht in einer hohen Niveau typsichere Sprache. (Wie auch immer, ich habe gehört, dass der XOR-Trick endet tatsächlich langsamer ist als eine temporäre Variable in vielen gängigen CPU-Architekturen verwenden.)

Sie sollten nur eine temporäre Variable verwenden. Es gibt keinen Grund, warum Sie nicht benutzen; es ist nicht so, es gibt ein begrenztes Angebot.

Im Interesse der Zukunft Lernenden und die Menschheit, lege ich diese Korrektur auf die aktuell ausgewählte Antwort.

Wenn Sie temporäre Variablen vermeiden möchten, gibt es nur zwei sinnvolle Optionen , die erste Aufführung nehmen und dann in Betracht Lesbarkeit.

  • Verwenden Sie eine temporäre Variable in einem allgemeinen Swap Verfahren. (Absolute beste Leistung, neben Inline-Temp-Variable)
  • Verwenden Sie Interlocked.Exchange . (5,9-mal langsamer auf meinem Rechner, aber das ist die einzige Option, wenn mehrere Threads diese Variablen gleichzeitig werden Swapping).

Was Sie sollten nie zu tun:

  • Nie Gleitkomma-Arithmetik verwenden. (Langsam, Runden und Überlauffehler, schwer zu verstehen)
  • Sie niemals nicht-primitive Arithmetik verwenden. (Langsam, Überlauffehler, schwer zu verstehen) Decimal ist keine CPU primitiv und führt zu weit mehr Code als Sie denken.
  • Nie arithmetische Periode verwenden. Oder Bit-Hacks. (langsam, schwer zu verstehen) Das ist die Aufgabe des Compilers. Es kann für viele verschiedene Plattformen optimieren.

Weil jede harte Zahl liebt, ist hier ein Programm, das Ihre Optionen vergleicht. Führen Sie es im Release-Modus von außen Visual Studio, so dass Swap inlined wird. Ergebnisse auf meinem Rechner (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();
    }
}

Sie können es in 3 Zeilen tun grundlegende mathematische mit - in meinem Beispiel I Multiplikation verwendet, aber einfache Addition auch funktionieren würde,

.
float startAngle = 159.9F;
float stopAngle = 355.87F;

startAngle = startAngle * stopAngle;
stopAngle = startAngle / stopAngle;
startAngle = startAngle / stopAngle;

Edit: Wie in den Kommentaren erwähnt, würde dies nicht funktionieren, wenn y = 0, da es eine Division durch Null-Fehler erzeugen würde, die ich hatte, nicht berücksichtigt. So ist die +/- Lösung alternativ vorgestellt wäre der beste Weg zu gehen.


Um meinen Code sofort verständlich zu halten, würde ich mich eher so etwas wie dies zu tun. [Denken Sie immer an den armen Kerl, der werde den Code zu halten ist haben]:

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 Sie können tun es in einer Codezeile:

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);

wie Abendessen Geschehen ... Sie jetzt in jeder Art von Objekt passieren kann und schalten sie um ...

Wenn Sie von der Verwendung decimal ändern können double Sie die Interlocked Klasse verwenden können. Vermutlich wird dies ein guter Weg, um zu tauschen Variablen weise Leistung. 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)

In C # 7:

(startAngle, stopAngle) = (stopAngle, startAngle);

Für die Vollständigkeit, hier ist 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 sie direkt mit dem Bytes beschäftigt, sondern können zu einem unsicheren Kontext erfordern auf Dezimalstellen arbeiten oder, wenn Sie wirklich verdreht sie fühlen, Zeiger. Und es kann sein, langsamer als eine temporäre Variable in einigen auch Umstände.

Achten Sie auf Ihre Umgebung!

Zum Beispiel, dies scheint nicht in ECMAscript arbeitet

y ^= x ^= y ^= x;

Aber das tut

x ^= y ^= x; y ^= x;

Mein Rat? Es sei angenommen, so wenig wie möglich.

Mit C # 7 können Sie Tupel Dekonstruktion verwenden, um die gewünschte Swap in einer Zeile zu erreichen, und es ist klar, was los ist.

decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);

(startAngle, stopAngle) = (stopAngle, startAngle);

Die einfache Art und Weise 2 Zahlen in nur eine Zeile zu tauschen:

a=(a+b)-(b=a);

Beispiel: a = 1, b = 2

Schritt 1: a = (1 + 2) - (b = 1)

Schritt 2: a = 3-1

=> a = 2 und b = 1


Effiziente Weise zu bedienen ist:

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: // Swap mit bitweise XOR (falsche Lösung in C / C ++)

x ^= y ^= x ^= y; 

Quelle: GeeksforGeek

a = a + b
b = a - b
a = a - b

Für binäre Typen können Sie diesen flippigen Trick verwenden:

a %= b %= a %= b;

Solange a und b sind nicht genau die gleiche Variable (z Aliase für den gleichen Speicher) es funktioniert.

Ich hoffe, dass dies helfen könnte ...

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);
    }
}

können wir tun, dass durch einen einfachen Trick tun

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);
startAngle = (startAngle + stopAngle) - (stopAngle = startAngle);

Mit Tupel

decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);

(startAngle, stopAngle) = (stopAngle, startAngle);

Wenn Sie zwei String-Variablen tauschen:

a = (a+b).Substring((b=a).Length);

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);

Hier ist ein weiterer Ansatz in einer Zeile ein:

decimal a = 159.9m;
decimal b = 355.87m;

a = b + (b = a) - b;

Hier ist etwas anderer Prozess zwei Variablen tauschen

//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);
var a = 15;
var b = -214;
a = b | !(b = a);

Dies funktioniert gut.

Sehr einfacher Code für das Wechseln 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();
}

Sie können den folgenden Code versuchen. Es ist viel besser als der andere Code.

a = a + b;
b = a - b;
a = a - b;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top