문제

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

MSDN : interlocked.exchange 메소드 (이중, 더블)

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;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top