C# で一時変数を使用せずに 2 つの変数を交換できるようにしたいと考えています。これはできますか?
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
// Swap each:
// startAngle becomes: 355.87
// stopAngle becomes: 159.9
2 つの変数を交換する正しい方法は次のとおりです。
decimal tempDecimal = startAngle;
startAngle = stopAngle;
stopAngle = tempDecimal;
つまり、一時変数を使用します。
そこにあります。巧妙なトリックも、何十年にもわたってあなたのコードのメンテナーがあなたをののしることも、The Daily WTFへのエントリもありません。最も複雑な言語機能は、一連の単純な操作です。
非常にシンプルで、読みやすく、理解しやすいt = a; a = b; b = t;
ソリューションです。
私の意見では、たとえば、「temp を使用せずに変数を交換する」または「Duff のデバイス」などのトリックを使用しようとする開発者は、自分がいかに賢いかを示そうとしているだけです (そして惨めに失敗しています)。
私は彼らを、(視野を広げるのではなく)パーティーでもっと面白く見せるためだけに高尚な本を読む人に例えます.
加算と減算を行うソリューション、または XOR ベースのソリューションは、単純な「一時変数」ソリューション (アセンブリ レベルでの単純な移動ではなく、算術/ブール演算) よりも読みにくく、おそらく遅くなります。
読みやすい高品質のコードを記述して、自分自身や他の人にサービスを提供してください。
それは私の暴言です。聞いてくれてありがとう :-)
余談ですが、これがあなたの特定の質問に答えていないことは承知しています(そして、それについてはお詫びします)が、人々が何かをする方法を尋ねたSOに関する前例がたくさんあり、正しい答えは「しないでください」ですやれ"。
まず第一に、C#として言語の一時変数なしで交換することは非常に悪い考えです。
しかし、答えのために、あなたはこのコードを使うことができます:
startAngle = startAngle + stopAngle;
stopAngle = startAngle - stopAngle;
startAngle = startAngle - stopAngle;
ただし、2つの数値が大きく異なる場合は、四捨五入で問題が発生する可能性があります。これは、浮動小数点数の性質によるものです。
一時変数を非表示にする場合は、ユーティリティメソッドを使用できます。
public static class Foo {
public static void Swap<T> (ref T lhs, ref T rhs) {
T temp = lhs;
lhs = rhs;
rhs = temp;
}
}
はい、次のコードを使用します。
stopAngle = Convert.ToDecimal(159.9);
startAngle = Convert.ToDecimal(355.87);
任意の値の場合、問題はより難しくなります。:-)
int a = 4, b = 6;
a ^= b ^= a ^= b;
文字列や浮動小数点数を含むすべての型で機能します。
BenAlabaster は、変数の切り替えを行う実用的な方法を示しましたが、try-catch 句は必要ありません。このコードで十分です。
static void Swap<T>(ref T x, ref T y)
{
T t = y;
y = x;
x = t;
}
使い方は彼が示したものと同じです:
float startAngle = 159.9F
float stopAngle = 355.87F
Swap(ref startAngle, ref stopAngle);
拡張メソッドを使用することもできます:
static class SwapExtension
{
public static T Swap<T>(this T x, ref T y)
{
T t = y;
y = x;
return t;
}
}
次のように使用します。
float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle.Swap(ref stopAngle);
どちらの方法でもメソッドで一時変数を使用しますが、スワッピングを行う一時変数は必要ありません。
C# にはありません。ネイティブ コードでは、トリプル XOR スワップ トリックを使用できる場合がありますが、高レベルのタイプ セーフ言語では使用できません。(とにかく、XOR のトリックは、多くの一般的な CPU アーキテクチャで一時変数を使用するよりも実際には遅くなると聞いています。)
一時変数を使用するだけです。使用できない理由はありません。供給が限られているわけではありません。
C# 7 の場合:
(startAngle, stopAngle) = (stopAngle, startAngle);
<非推奨>
基本的な数学を使用して 3 行で実行できます。私の例では乗算を使用しましたが、単純な加算でも機能します。
float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle * stopAngle;
stopAngle = startAngle / stopAngle;
startAngle = startAngle / stopAngle;
編集:コメントに記載されているように、y = 0 の場合、考慮していなかったゼロ除算エラーが発生するため、これは機能しません。したがって、代わりに提示された +/- ソリューションが最善の方法です。
</非推奨>
コードをすぐに理解できるようにするために、このようなことをする可能性が高くなります。[あなたのコードを維持しなければならない可哀想な人のことを常に考えてください]:
static bool Swap<T>(ref T x, ref T y)
{
try
{
T t = y;
y = x;
x = t;
return true;
}
catch
{
return false;
}
}
そして、それを 1 行のコードで実行できます。
float startAngle = 159.9F
float stopAngle = 355.87F
Swap<float>(ref startAngle, ref stopAngle);
または...
MyObject obj1 = new MyObject("object1");
MyObject obj2 = new MyObject("object2");
Swap<MyObject>(ref obj1, ref obj2);
夕食のように完了...任意のタイプのオブジェクトを渡して、それらを切り替えることができます...
完全を期すために、バイナリ XOR スワップを次に示します。
int x = 42;
int y = 51236;
x ^= y;
y ^= x;
x ^= y;
これは、バイトを直接処理するため、すべてのアトミック オブジェクト/参照に対して機能しますが、10 進数を処理するには安全でないコンテキストが必要になる場合があります。また、状況によっては一時変数よりも遅くなる場合もあります。
decimal
使用から変更double
できる場合は、Interlocked
クラスを使用できます。おそらく、これはパフォーマンスに関して変数を交換する良い方法になるでしょう。また、XOR よりもわずかに読みやすい。
var startAngle = 159.9d;
var stopAngle = 355.87d;
stopAngle = Interlocked.Exchange(ref startAngle, stopAngle);
C# 7 では、タプルの分解を使用して目的のスワップを 1 行で実現でき、何が起こっているかは明らかです。
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
(startAngle, stopAngle) = (stopAngle, startAngle);
a = a + b
b = a - b
a = a - b
َ
あなたの環境に注意してください!
たとえば、これは ECMAscript では機能しないようです
y ^= x ^= y ^= x;
しかし、これは
x ^= y ^= x; y ^= x;
私のアドバイス?できるだけ少ないと仮定します。
2 つの数字を 1 行で入れ替える簡単な方法:
a=(a+b)-(b=a);
例: a=1、b=2
ステップ 1: a=(1+2) - (b=1)
ステップ 2: a=3-1
=> a=2 かつ b=1
効率的な方法は、次を使用することです。
C プログラミング: (x ^= y), (y ^= x), (x ^= y);
ジャワ: x = x ^ y ^ (y = x);
パイソン:x, y = y, x
注:最も一般的な間違い: //ビットごとの XOR を使用して交換する (C/C++ での間違った解決策)
x ^= y ^= x ^= y;
ソース: GeeksforGeek
バイナリタイプの場合、このファンキーなトリックを使用できます。
a %= b %= a %= b;
aとbがまったく同じ変数(たとえば、同じメモリのエイリアス)でない限り、機能します。
これが役立つことを願っています...
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);
}
}
startAngle = (startAngle + stopAngle) - (stopAngle = startAngle);
var a = 15;
var b = -214;
a = b | !(b = a);
これはうまくいきます。
2 つの変数を交換するための非常に単純なコード:
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();
}
次のコードを試すことができます。他のコードよりもはるかに優れています。
a = a + b;
b = a - b;
a = a - b;