임시 변수를 사용하지 않고 두 변수 교체
C #에서 임시 변수를 사용하지 않고 두 변수를 바꿀 수 있기를 바랍니다. 할 수 있습니까?
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
// Swap each:
// startAngle becomes: 355.87
// stopAngle becomes: 159.9
우선, C # 언어에서 임시 변수없이 교체하는 것은 매우 나쁜 생각 입니다.
그러나 대답을 위해 다음 코드를 사용할 수 있습니다.
startAngle = startAngle + stopAngle;
stopAngle = startAngle - stopAngle;
startAngle = startAngle - stopAngle;
그러나 두 숫자가 크게 다를 경우 반올림 문제가 발생할 수 있습니다. 이것은 부동 소수점 숫자의 특성 때문입니다.
임시 변수를 숨기려면 유틸리티 메서드를 사용할 수 있습니다.
public static class Foo {
public static void Swap<T> (ref T lhs, ref T rhs) {
T temp = lhs;
lhs = rhs;
rhs = temp;
}
}
바로 두 개의 변수를 교환하는 방법입니다 :
decimal tempDecimal = startAngle;
startAngle = stopAngle;
stopAngle = tempDecimal;
즉, 임시 변수를 사용하십시오.
거기에 있습니다. 영리한 속임수도없고, 앞으로 수십 년 동안 당신을 저주하는 코드 관리자도없고, The Daily WTF에 대한 항목 도 없으며, 최하위 수준에서 심지어는 한 번의 작업에서 왜 필요한지 알아 내려고 너무 많은 시간을 소비하지 않습니다. 가장 복잡한 언어 기능은 일련의 간단한 작업입니다.
매우 간단하고 읽기 쉽고 이해하기 쉬운 t = a; a = b; b = t;
솔루션입니다.
제 생각에는 "임시를 사용하지 않고 변수를 교체"하거나 "더프의 장치"와 같이 트릭을 사용하려는 개발자는 단지 그들이 얼마나 영리하고 비참하게 실패하는지 보여 주려고합니다.
나는 그들을 (당신의 시야를 넓히는 것과는 반대로) 파티에서 더 흥미로워 보일 목적으로 만 하이 브로우 책을 읽는 사람들에 비유합니다.
더하고 빼는 솔루션 또는 XOR 기반 솔루션은 읽기가 어렵고 단순한 "임시 변수"솔루션 (어셈블리 수준에서 일반 이동 대신 산술 / 부울 연산)보다 느립니다.
좋은 품질의 읽기 가능한 코드를 작성하여 자신과 다른 사람들에게 서비스를 제공하십시오.
그게 내 폭언입니다. 듣기 주셔서 감사합니다 :-)
제쳐두고, 나는 이것이 당신의 특정 질문에 대답하지 않는다는 것을 잘 알고 있습니다 (그리고 그것에 대해 사과 할 것입니다) 사람들이 무언가를하는 방법을 묻고 정답은 "하지 마십시오 해".
C # 7에서는 임시 변수없이 두 개의 변수를 바꿀 수 있는 튜플 을 도입했습니다 .
int a = 10;
int b = 2;
(a, b) = (b, a);
이것은 b
에 a
및 a
에 할당 됩니다 b
.
예, 다음 코드를 사용하십시오.
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);
두 가지 방법 모두 메서드에서 임시 변수를 사용하지만 스와핑을 수행하는 곳에 임시 변수가 필요하지 않습니다.
자세한 예제가 포함 된 바이너리 XOR 스왑 :
XOR 진리표 :
a b a^b
0 0 0
0 1 1
1 0 1
1 1 0
입력:
a = 4;
b = 6;
1 단계 : a = a ^ b
a : 0100
b : 0110
a^b: 0010 = 2 = a
2 단계 : b = a ^ b
a : 0010
b : 0110
a^b: 0100 = 4 = b
3 단계 : a = a ^ b
a : 0010
b : 0100
a^b: 0110 = 6 = a
산출:
a = 6;
b = 4;
미래의 학습자와 인류를 위해 현재 선택된 답변에이 수정 사항을 제출합니다.
임시 변수를 사용하지 않으 려면 먼저 성능을 고려한 다음 가독성을 고려하는 두 가지 합리적인 옵션 만 있습니다 .
- 일반
Swap
메서드 에서 임시 변수를 사용합니다 . (절대 최고 성능, 인라인 임시 변수 옆) - 사용
Interlocked.Exchange
. (내 컴퓨터에서는 5.9 배 느리지 만 여러 스레드가 이러한 변수를 동시에 스왑하는 경우 유일한 옵션입니다.)
절대 하지 말아야 할 것 :
- 부동 소수점 산술을 사용하지 마십시오. (느림, 반올림 및 오버플로 오류, 이해하기 어려움)
- 원시가 아닌 산술을 사용하지 마십시오. (느림, 오버플로 오류, 이해하기 어려운)
Decimal
CPU 기본 요소가 아니며 사용자가 생각하는 것보다 훨씬 많은 코드가 생성됩니다. - 산술 기간을 사용하지 마십시오. 또는 약간의 해킹. (느리고 이해하기 어렵습니다) 그게 컴파일러의 일입니다. 다양한 플랫폼에 최적화 할 수 있습니다.
모두가 어려운 숫자를 좋아하기 때문에 옵션을 비교하는 프로그램이 있습니다. Visual Studio 외부에서 릴리스 모드로 실행하여 Swap
인라인 되도록합니다 . 내 컴퓨터의 결과 (Windows 7 64 비트 i5-3470) :
Inline: 00:00:00.7351931
Call: 00:00:00.7483503
Interlocked: 00:00:04.4076651
암호:
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();
}
}
C #이 아닙니다. 네이티브 코드에서는 triple-XOR 스왑 트릭을 사용할 수 있지만 높은 수준의 형식 안전 언어에서는 사용할 수 없습니다. (어쨌든 나는 XOR 트릭이 실제로 많은 일반적인 CPU 아키텍처에서 임시 변수를 사용하는 것보다 느리다고 들었습니다.)
임시 변수를 사용해야합니다. 사용할 수없는 이유는 없습니다. 제한된 공급이있는 것과는 다릅니다.
<사용되지 않음>
기본 수학을 사용하여 3 줄로 할 수 있습니다. 제 예에서는 곱셈을 사용했지만 간단한 덧셈도 작동합니다.
float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle * stopAngle;
stopAngle = startAngle / stopAngle;
startAngle = startAngle / stopAngle;
편집 : 주석에서 언급했듯이 y = 0이면 고려하지 않은 0으로 나누기 오류가 발생하므로 작동하지 않습니다. 따라서 대안으로 제시된 +/- 솔루션이 가장 좋은 방법입니다.
</ 지원 중단됨>
내 코드를 즉시 이해할 수 있도록 유지하려면 이와 같은 작업을 수행 할 가능성이 더 큽니다. [항상 코드를 유지해야하는 가난한 사람에 대해 생각하세요] :
static bool Swap<T>(ref T x, ref T y)
{
try
{
T t = y;
y = x;
x = t;
return true;
}
catch
{
return false;
}
}
그런 다음 한 줄의 코드로 수행 할 수 있습니다 .
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);
저녁 식사처럼 끝났어 ... 이제 모든 유형의 물건을 전달하고 전환 할 수 있습니다 ...
사용에서 decimal
로 변경할 수 있으면 수업을 double
사용할 수 있습니다 Interlocked
. 아마도 이것은 변수 성능을 현명하게 바꾸는 좋은 방법이 될 것입니다. 또한 XOR보다 약간 더 읽기 쉽습니다.
var startAngle = 159.9d;
var stopAngle = 355.87d;
stopAngle = Interlocked.Exchange(ref startAngle, stopAngle);
Msdn : Interlocked.Exchange 메서드 (Double, Double)
C # 7 :
(startAngle, stopAngle) = (stopAngle, startAngle);
완전성을 위해 다음은 바이너리 XOR 스왑입니다.
int x = 42;
int y = 51236;
x ^= y;
y ^= x;
x ^= y;
이것은 바이트를 직접 처리하기 때문에 모든 원자 객체 / 참조에 대해 작동하지만 소수점 또는 실제로 뒤틀린 느낌이 든다면 포인터에서 작동하려면 안전하지 않은 컨텍스트가 필요할 수 있습니다. 또한 어떤 상황에서는 임시 변수보다 느릴 수도 있습니다.
C # 7에서는 튜플 분해를 사용하여 한 줄로 원하는 스왑을 달성 할 수 있으며 무슨 일이 일어나고 있는지 분명합니다.
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
(startAngle, stopAngle) = (stopAngle, startAngle);
환경을 조심하십시오!
예를 들어, 이것은 ECMAscript에서 작동하지 않는 것 같습니다.
y ^= x ^= y ^= x;
그러나 이것은
x ^= y ^= x; y ^= x;
내 조언? 가능한 한 적게 가정하십시오.
한 줄로 2 개의 숫자를 바꾸는 간단한 방법 :
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 = a + b
b = a - b
a = a - b
َ
바이너리 유형의 경우 다음과 같은 펑키 한 트릭을 사용할 수 있습니다.
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);
}
}
간단한 트릭을 사용하여
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);
튜플 사용
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
(startAngle, stopAngle) = (stopAngle, startAngle);
startAngle = (startAngle + stopAngle) - (stopAngle = startAngle);
2 개의 문자열 변수를 바꾸려면 :
a = (a+b).Substring((b=a).Length);
이에 따른 도우미 메서드 :
public static class Foo {
public static void SwapString (ref string a, ref string b) {
a = (a+b).Substring((b=a).Length);
}
}
사용법은 다음과 같습니다.
string a="Test 1";
string b="Test 2";
Foo.SwapString(a, b);
한 줄에 또 다른 접근 방식이 있습니다.
decimal a = 159.9m;
decimal b = 355.87m;
a = b + (b = a) - b;
다음은 두 개의 변수를 교환하는 몇 가지 다른 프로세스입니다.
//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);
이것은 훌륭하게 작동합니다.
두 변수를 교환하는 매우 간단한 코드 :
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;
참고URL : https://stackoverflow.com/questions/804706/swap-two-variables-without-using-a-temporary-variable
'Nice programing' 카테고리의 다른 글
TypeError : db.collection이 함수가 아닙니다. (0) | 2020.11.25 |
---|---|
JavaScript Standard Style은 Mocha를 인식하지 못합니다. (0) | 2020.11.25 |
Angular2 Dart에서 Router 및 RouterLink를 설정하는 올바른 방법은 무엇입니까? (0) | 2020.11.25 |
CGAssociateMouseAndMouseCursorPosition 감지 (0) | 2020.11.25 |
cout << myclass를 어떻게 사용할 수 있습니까? (0) | 2020.11.24 |