什么是不变量?

时间:2008-09-21 20:42:21

标签: language-agnostic invariants

这个词似乎在许多情况下被使用。我能想到的最好的是它们意味着一个无法改变的变量。是不是常数/决赛(你是Java!)是为了什么?

13 个答案:

答案 0 :(得分:146)

不变量比变量更“概念化”。通常,程序状态的属性始终为true。确保不变量成立的函数或方法据说可以保持不变量。

例如,二叉搜索树可能具有不变量,对于每个节点,节点的左子节点的键小于节点自己的键。正确编写此树的插入函数将保持不变。

正如您所知,这不是您可以存储在变量中的那种东西:它更像是关于程序的声明。通过确定程序应该维护哪种不变量,然后查看代码以确保它实际维护这些不变量,可以避免代码中的逻辑错误。

答案 1 :(得分:24)

这是一个条件,你知道在逻辑中的某个特定位置始终是真的,并且可以检查何时调试以找出出错的地方。

答案 2 :(得分:14)

我通常在算法或结构方面更多地查看它们。

例如,您可以拥有一个可以断言的循环不变量 - 在每次迭代的开始或结束时始终为true。也就是说,如果你的循环应该处理从一个堆栈到另一个堆栈的对象集合,你可以在循环的顶部或底部说| stack1 | + | stack2 | = c。

如果不变检查失败,则表示出现了问题。在这个例子中,它可能意味着您忘记将已处理的元素推送到最终堆栈等。

答案 3 :(得分:13)

维基百科的魔力:Invariant (computer science)

  

在计算机科学中,一个谓词,   如果是真的,将在整个过程中保持真实   具体的操作顺序是   称(a)对此不变   序列

答案 4 :(得分:6)

正如这条线所述:

  

在计算机科学中,一个谓词,如果是真的,将在整个特定的操作序列中保持为真,称为(a)对该序列不变。

为了更好地理解这个希望,C ++中的这个例子有帮助。

考虑一个场景,您必须获取一些值,并在名为count的变量中获取它们的总数,并将它们添加到名为sum

的变量中

不变(再次更像是一个概念):

// invariant:
// we have read count grades so far, and
// sum is the sum of the first count grades

上面的代码就是这样的,

int count=0;
double sum=0,x=0;
while (cin >> x) {
++count;
sum+=x;
}

以上代码的作用是什么?

1)从cin读取输入并将其放入x

2)成功阅读一次后,增加countsum = sum + x

3)重复1-2直到读取停止(即ctrl + D)

循环不变量:

不变量必须为True 始终。所以最初你只用这个

开始你的代码
while(cin>>x){
  }

此循环从标准输入读取数据并存储在x中。好,好。但不变会变为false,因为不变的第一部分未被跟踪(或保持为真)。

// we have read count grades so far, and

如何保持不变量?

简单!增量计数。

所以++count;会做得好!现在我们的代码就像这样,

while(cin>>x){
 ++count; 
 }

但是

即使现在我们的不变(一个必须为TRUE的概念)也是假的,因为现在我们没有满足我们的不变量的第二部分。

// sum is the sum of the first count grades

那现在该怎么办?

x添加到sum并将其存储在sumsum+=x)中,然后再次 cin>>x会将新值读入x。

现在我们的代码就像这样,

while(cin>>x){
 ++count; 
 sum+=x;
 }

我们来检查

代码是否与我们的不变量

匹配
// invariant:
// we have read count grades so far, and
// sum is the sum of the first count grades

代码:

while(cin>>x){
 ++count; 
 sum+=x;
 }

啊!现在循环不变量是True 始终并且代码工作正常。

以上示例是本书加速C ++ 中获取并修改了Andrew-koening和Barbara-E

答案 5 :(得分:4)

在代码块中没有改变的东西

答案 6 :(得分:3)

此答案适用于我5岁的孩子。不要将不变量视为常数或固定数值。但是可以。但是,不仅如此。

相反,不变性类似于各种实体之间的固定关系。例如,与您的亲生父母相比,您的年龄将始终小于其年龄。您的年龄和父母的年龄都会随着时间的推移而变化,但是我上面提到的关系是不变的。

不变式也可以是数字常数。例如,pi的值是圆的周长与其直径之间的不变比率。无论圆的大小,该比例始终为pi

答案 7 :(得分:2)

继续它之后,不变量在编写干净的代码时非常有用,因为从概念上了解应该在代码中出现的不变量允许您轻松决定如何组织代码以达到这些代码旨在。如上所述,它们在调试时也很有用,因为检查是否维护不变量通常是一种很好的方式,可以看出你试图执行的操作是否实际上正在按照你想要的方式进行。

答案 8 :(得分:2)

通常是在某些数学运算下不会改变的数量。 示例是标量,在旋转时不会改变。例如,在磁共振成像中,通过旋转不变量来表征组织特性很有用,因为理想情况下,其估计值不取决于扫描仪中人体的方向。

答案 9 :(得分:1)

ADT不变量指定关系 在数据字段中(实例变量) 之前和之后必须始终如一 执行任何实例方法。

答案 10 :(得分:0)

Java Concurrency in Practice一书中有一个很好的例子,说明了不变性及其重要性。

尽管此示例以Java为中心,但该示例描述了一些代码,这些代码负责计算所提供整数的因数。示例代码尝试缓存提供的最后一个数字以及为提高性能而计算出的因素。在这种情况下,示例代码中没有说明一个不变式,这使得该代码在并发场景中容易出现竞争条件。

enter image description here

答案 11 :(得分:0)

这里的所有答案都很好,但是我觉得我可以进一步阐明这件事:

从语言的角度来看,不变是指永远不变的东西。这个概念虽然实际上来自数学,但与归纳相结合是一种流行的证明技术。

这里是证明的过程,如果您可以找到处于初始状态的不变量,并且无论该状态适用任何[合法]转换,该不变量都将持续存在,那么您可以证明如果某个状态确实存在没有这种不变性,那么无论将什么顺序的转换应用于初始状态,它都永远不会发生。

现在,先前的思维方式(再次与归纳相结合)使得可以断定计算机软件的逻辑。当执行进入循环时,这一点尤其重要,在循环中可以使用不变式来证明某个循环将产生某种结果,或者它永远不会以某种方式改变程序的状态。

使用不变式作为循环逻辑的谓词时,其称为loop invariant。可以在循环外使用它,但是对于循环来说,它确实很重要,因为您经常有很多可能性,或者有无限多种可能性。

请注意,我使用“谓词”一词是计算机软件的逻辑,而不是证明。那是因为虽然在数学invariant中可以用作证明,但是由于该软件是在许多抽象之上执行的事实,因此它永远无法证明计算机软件在执行时会产生预期的效果。永远无法证明它们会达到预期的效果(例如,考虑硬件抽象)。

最后,虽然理论上和严格地预测软件逻辑仅对医疗和军事等高关键应用程序很重要。在调试时,仍然可以使用不变式来帮助典型的程序员。它可以用来知道程序在某个特定位置的位置,因为该程序无法维护某个不变式而导致失败-我们中的许多人无论如何都在使用它而没有考虑它。

答案 12 :(得分:0)

Class Invariant是一个条件,在调用相关函数前后应该始终为真

例如,平衡树具有Invariant的{​​{1}}。通过某些方法(例如addNode,removeNode ...)修改树时,isBalanced在修改树之前和之后都应始终为真