All,
我正在尝试调整一些 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 如何评估作业?为什么当我将多个作业分解为单个作业时,结果会有所不同?
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 表达式之前,a
或b
的值不会从其初始值更改。
与 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
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)
因此,结果是不同的。
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
问题是,在作业中
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
以避免过早计算表达式的影响。