임시 변수를 사용하지 않고 두 변수를 교체하십시오
문제
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;
다시 말해, 임시 변수를 사용하십시오.
당신은 그것을 가지고 있습니다. 영리한 속임수 없음, 코드의 관리자는 앞으로 수십 년 동안 당신을 저주하고, 출품작 없음 매일 WTF, 어쨌든 가장 낮은 수준에서 가장 복잡한 언어 기능조차도 일련의 간단한 운영이기 때문에 어쨌든 한 작업에서 필요한 이유를 알아 내려고 너무 많은 시간을 소비하지 않습니다.
매우 간단하고 읽기 쉽고 이해하기 쉽습니다. t = a; a = b; b = t;
해결책.
제 생각에, 예를 들어 "온도를 사용하지 않고 변수를 바꾸는"또는 "더프의 장치"와 같은 트릭을 사용하려는 개발자는 단지 자신이 얼마나 영리하고 (비참하게 실패하는지) 보여 주려고 노력하고 있습니다.
나는 파티에서 더 흥미로운 것처럼 보이기 위해서만 Highbrow 책을 읽는 사람들에게 비유합니다 (당신의 지평을 확장하는 것과 대조).
추가 및 빼기 또는 XOR 기반 용액은 읽기 쉬운 솔루션이 덜 읽기 쉬우 며 간단한 "임시 변수"솔루션 (어셈블리 수준에서 일반 이동 대신 산술/부울 -OPS)보다 느리게 가능합니다.
양질의 읽기 쉬운 코드를 작성하여 자신과 다른 사람에게 서비스를하십시오.
그게 내 분노 야. 듣기 주셔서 감사합니다 :-)
제쳐두고, 나는 이것이 당신의 구체적인 질문에 대답하지 않는다는 것을 알고 있습니다 (그리고 그것에 대해 사과 할 것입니다) 사람들이 무언가를하는 방법을 물었고 정답은 "하지 않는 것입니다. 해".
예,이 코드를 사용하십시오.
stopAngle = Convert.ToDecimal(159.9);
startAngle = Convert.ToDecimal(355.87);
임의의 값은 문제가 더 어렵습니다. :-)
C# 7 도입 튜플 임시 변수없이 두 개의 변수를 교환 할 수 있습니다.
int a = 10;
int b = 2;
(a, b) = (b, a);
이것은 할당됩니다 b
에게 a
그리고 a
에게 b
.
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;
C#에 있지 않습니다. 기본 코드에서는 트리플 XOR 스왑 트릭을 사용할 수 있지만 높은 수준의 유형 안전 언어는 사용할 수 없습니다. (어쨌든, 나는 XOR 트릭이 실제로 많은 일반적인 CPU 아키텍처에서 임시 변수를 사용하는 것보다 느리게 진행된다고 들었습니다.)
임시 변수 만 사용해야합니다. 당신이 하나를 사용할 수없는 이유는 없습니다. 공급이 제한된 것과는 다릅니다.
미래의 학습자와 인류를 위해, 나는이 수정 사항을 현재 선택된 답변에 제출합니다.
온도 변수 사용을 피하려면 두 가지 현명한 옵션 만 첫 번째 성능과 가독성을 고려합니다.
- 일반적인 임시 변수를 사용하십시오
Swap
방법. (인라인 온도 변수 옆에 절대 최고의 성능) - 사용
Interlocked.Exchange
. (내 컴퓨터에서 5.9 배 느리지만 여러 스레드가 이러한 변수를 동시에 바꾸는 경우 유일한 옵션입니다.)
당신이해야 할 것들 절대 하다:
- 플로팅 포인트 산술을 사용하지 마십시오. (느린, 반올림 및 오버플로 오류, 이해하기 어려운)
- 비-프리비틱 산술을 사용하지 마십시오. (느리고 오버플로 오류, 이해하기 어려운)
Decimal
CPU 원시가 아니며 당신이 알고있는 것보다 훨씬 더 많은 코드를 초래합니다. - 산술 기간을 사용하지 마십시오. 또는 비트 핵. (느리고 이해하기 어렵습니다) 그게 컴파일러의 작업입니다. 다양한 플랫폼에 대해 최적화 할 수 있습니다.
모두가 어려운 숫자를 좋아하기 때문에 다음은 옵션을 비교하는 프로그램입니다. 외부 비주얼 스튜디오에서 릴리스 모드로 실행하여 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();
}
}
u003Cdeprecated>
기본 수학을 사용하여 3 줄로 할 수 있습니다. 내 예에서는 곱셈을 사용했지만 간단한 추가도 작동합니다.
float startAngle = 159.9F;
float stopAngle = 355.87F;
startAngle = startAngle * stopAngle;
stopAngle = startAngle / stopAngle;
startAngle = startAngle / stopAngle;
편집 : 주석에서 언급 한 바와 같이, 이것은 내가 고려하지 않은 0 오류로 분할을 생성하므로 y = 0이면 작동하지 않습니다. 따라서 대안 적으로 제시된 +/- 솔루션이 가장 좋은 방법이 될 것입니다.
u003C/deprecated>
내 코드를 즉시 이해할 수있게하려면 이와 같은 일을 할 가능성이 더 높습니다. [코드를 유지 해야하는 가난한 사람에 대해 항상 생각해보십시오.] :
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);
C# 7에서 :
(startAngle, stopAngle) = (stopAngle, startAngle);
완전성을 위해 여기 Binains XOR 스왑이 있습니다.
int x = 42;
int y = 51236;
x ^= y;
y ^= x;
x ^= y;
이것은 바이트를 직접 다루기 때문에 모든 원자 객체/참조에 대해 작동하지만, 소수성에 대해 또는 실제로 뒤틀린 느낌이 들었을 때는 안전하지 않은 컨텍스트가 필요할 수 있습니다. 그리고 일부 상황에서도 임시 변수보다 느리게 될 수 있습니다.
당신의 환경을 조심하십시오!
예를 들어, 이것은 ecmascript에서 작동하지 않는 것 같습니다.
y ^= x ^= y ^= x;
그러나 이것은 그렇습니다
x ^= y ^= x; y ^= x;
내 조언? 가능한 한 적은 것으로 가정합니다.
C# 7을 사용하면 튜플 해체를 사용하여 원하는 스왑을 한 줄로 달성 할 수 있으며 무슨 일이 일어나고 있는지 분명합니다.
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
(startAngle, stopAngle) = (stopAngle, startAngle);
단 한 줄만으로 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
메모: 사람들이하는 가장 일반적인 실수 :// bitwise 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);
startAngle = (startAngle + stopAngle) - (stopAngle = startAngle);
튜플로
decimal startAngle = Convert.ToDecimal(159.9);
decimal stopAngle = Convert.ToDecimal(355.87);
(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;