Ruby 整数赋值 - 将 Ruby 赋值改编为 C 类型语言



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 = 5b = 7q = 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

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

以避免过早计算表达式的影响。

最新更新