0

全部,

我正在尝试调整一些 Ruby 代码以在 C# 中工作,但 C# 不提供与 Ruby 相同的可用赋值语法

这是我正在尝试调整的一些 Ruby 代码:

    x, x1 = x1, x-q*x1
    y, y1 = y1, y-q*y1
    a, b  =  b, a-q*b

所以,我接受了它并做了这个,但我得到了与上面不同的结果:

    x = x1
    x1 = x-q*x1
    y = y1
    y1 = y-q*y1
    a = b
    b  = a-q*b

Ruby 如何评估作业?为什么当我将多个作业分成单个作业时结果不同?

4

4 回答 4

2

Ruby 首先计算 RHS 上的每个表达式,然后将它们分配给相应的 LHS 变量。

下面是(基本上)Ruby 如何评估第三行a, b = b, a-q*b

temp1 = b
temp2 = a-q*b
a = temp1
b = temp2

a = 5带有,b = 7和的示例q = 10

a, b = (7), (5 - 10*7)

产量

a == 7
b == -65

如您所见,在评估使用它的 RHS 表达式之前,没有值ab从其初始值更改。

与您的 C# 代码中发生的情况对比:

a = b      // a is changed BEFORE evaluating the value
           //   that will be put into b
b = a-q*b  // The value of a has already been changed:
           //   this is now the same as b = b-q*b, which is not intended

使用与上述相同值的示例结果:

a == 7
b == 7 - 10*7 == -63  // Not what we want...

要获得正确的结果,请在此答案的顶部使用带有临时变量的多行赋值:

temp1 = b       // 7
temp2 = a-q*b   // 5 - 10*7 == -65
a = temp1       // 7
b = temp2       // -65
于 2013-10-01T15:15:42.100 回答
1

Ruby 在重新分配变量之前评估赋值的右侧。为了使这一点更明确,它正在做这样的事情:

new_x, new_x1 = old_x1, old_x-q*old_x1

这导致:

new_x = old_x1
new_x1 = old_x-q*old_x1

但你正在做的是:

new_x = old_x1
new_x1 = new_x-q*old_x1 (= old_x1 - q * old_x1 = (1 - q) * old_x1)

因此结果是不同的。

于 2013-10-01T15:14:11.957 回答
0

问题是,在作业中

x, x1 = x1, x-q*x1

在执行任一赋值之前, Ruby在右侧计算两个表达式。但是如果你写

x = x1
x1 = x-q*x1

那么因为第一条语句修改了x的值,所以表达式的值x-q*x1也发生了变化。

你需要使用一个临时变量,像这样

newx = x1
x1 = x-q*x1
x = newx

以避免过早评估表达式的影响。

于 2013-10-01T15:16:13.637 回答
0

该行x, x1 = x1, x-q*x1意味着 x 和 x1 将基本上同时分配,但您的 C# 变体没有考虑到这一点。在您的 c# 代码中,x 将在 x1 之前分配,因此 x1 将被分配x1-q*x1,而不是x-q*x1因为此时 x 已被分配为 x1。

一个可能的通用 C# 解决方案是

tempX = x1
tempX1 = x-q*x1
x = tempX
x1 = tempX1
于 2013-10-01T15:14:02.733 回答