我想可以交换两个变量,而无需使用一种临时可变。可以这样做?

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;解决方案。

在我看来,尝试使用技巧的开发人员,例如,<!>交换变量而不使用temp <!>;或者<!>“; Duff的设备<!>”;只是想表明他们有多聪明(并且悲惨地失败)。

我把它们比作那些阅读高雅书籍的人,仅仅是为了在派对上看起来更有趣(而不是扩大你的视野)。

您添加和减去的解决方案,或基于XOR的解决方案,其可读性较差,并且可能比简单的<!>“temp变量<!>更慢;解决方案(arithmetic / boolean-ops而不是在程序集级别的plain移动)。

通过编写高质量的可读代码,为自己和他人提供服务。

那是我的咆哮。感谢您的收听: - )

顺便说一句,我很清楚这不会回答你的具体问题(我会为此道歉)但是在SO上有很多先例,人们已经问过如何做某事并且正确答案是< !>“不要这样做<!>”。

是的,请使用以下代码:

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

任意值的问题都比较困难。 : - )

C#7介绍元组 可以在没有临时变量的情况下交换两个变量:

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

这会将b分配给a,<=>分配给<=>。

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原始和结果远远更多的代码比你认识。
  • 从来没有使用算术运算周期。 或位黑客。 (慢,难以理解的),编译器的工作。它可以优化对于许多不同的平台。

因为每个人都喜欢的硬数据,这是一个程序,比较了你的选择。运行中释放的模式从外Visual Studio这样 Swap 是内联。结果我的机器上(Windows7 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();
    }
}

LT <!>;弃用GT <!>;

你可以使用基本数学在3行中完成 - 在我的例子中我使用了乘法,但是简单的加法也可以。

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

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

编辑:如评论中所述,如果y = 0,这将无效,因为它会产生除以零的错误,我没有考虑过。所以+/-解决方案交替呈现将是最好的方式。

LT <!>; /弃用GT <!>;


为了让我的代码立即易于理解,我更有可能做这样的事情。 [总是想想那个必须维护代码的穷人]:

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 Method(Double,Double)

在C#7中:

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

为了完整性,这里是二进制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

<!>

= GT; a = 2且b = 1


有效的方法是使用:

C编程:(x ^= y), (y ^= x), (x ^= y);

Java:x = x ^ y ^ (y = x);

Python:x, y = y, x

注意:人们犯的最常见错误: //使用按位XOR交换(C / C ++中的错误解决方案)

x ^= y ^= x ^= y; 

来源: GeeksforGeek

a = a + b
b = a - b
a = a - b
<!>

#1614;

对于二进制类型,您可以使用这个时髦的技巧:

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