173

这个词似乎在许多情况下使用。我能想到的最好的是它们意味着一个无法改变的变量。这不是常量/finals(该死的Java!)的用途吗?

4

13 回答 13

243

不变量比变量更“概念化”。通常,它是程序状态的属性,始终为真。确保不变量成立的函数或方法被称为保持不变量。

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

如您所知,这不是您可以存储在变量中的那种东西:它更多的是关于程序的陈述。通过弄清楚你的程序应该维护什么样的不变量,然后检查你的代码以确保它确实维护了这些不变量,你可以避免代码中的逻辑错误。

于 2008-09-21T20:48:21.030 回答
38

这是您知道在逻辑中的特定位置始终为真的条件,并且可以在调试时检查以找出问题所在。

于 2008-09-21T20:44:13.350 回答
22

维基百科的魔力:不变量(计算机科学)

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

于 2008-09-21T20:45:25.700 回答
17

我通常更多地从算法或结构的角度来看待它们。

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

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

于 2008-09-21T20:45:19.710 回答
13

这个答案是给我 5 岁的孩子的。不要将不变量视为常数或固定数值。但它可以。然而,它不止于此。

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

不变量也可以是数值常数。例如, 的值pi是圆的周长与其直径之间的不变比率。不管圆有多大或多小,这个比例永远是pi

于 2020-01-21T11:01:49.893 回答
11

正如这一行所述:

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

为了更好地理解这一点,希望这个 C++ 示例有所帮助。

考虑一个场景,您必须获取一些值并在名为 as 的变量中获取它们的总数,count然后将它们添加到名为 as 的变量中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 ALWAYS。所以最初你只用这个开始你的代码

while(cin>>x){
  }

此循环从标准输入读取数据并存储在 x 中。好和好。但是不变量变成了假,因为我们的不变量的第一部分没有被遵循(或保持为真)。

// we have read count grades so far, and

如何保持不变量为真?

简单的!递增计数。

所以++count;会做得很好!现在我们的代码变成了这样,

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

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

// sum is the sum of the first count grades

那么现在该怎么办呢?

添加xsum存储在sum( sum+=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并且代码工作正常。

上面的示例取自Andrew-koening 和 Barbara-E的《 Accelerated C++》一书并对其进行了修改

于 2017-09-05T12:52:34.867 回答
4

在代码块中不会改变的东西

于 2008-09-21T21:16:24.567 回答
2

从本质上讲,不变量在编写干净的代码时非常有用,因为从概念上了解代码中应该存在哪些不变量可以您轻松决定如何组织代码以实现这些目标。如前所述,它们在调试中也很有用,因为检查不变量是否被维护通常是查看您尝试执行的任何操作是否确实在执行您想要的操作的好方法。

于 2008-09-21T21:01:17.100 回答
2

它通常是在某些数学运算下不会改变的量。一个例子是一个标量,它在旋转下不会改变。例如,在磁共振成像中,通过旋转不变量来表征组织特性是有用的,因为这样它的估计理想地不依赖于身体在扫描仪中的方向。

于 2018-11-10T13:40:03.397 回答
2

这里的所有答案都很好,但我觉得我可以更清楚地说明这个问题:

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

下面是一个证明的过程,如果你能找到一个处于初始状态的不变量,并且不管对该状态应用任何 [合法] 变换,这个不变量仍然存在,那么你可以证明如果某个状态没有这个invariant 那么它永远不会发生,无论对初始状态应用什么变换序列。

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

当不变量用于谓词循环逻辑时,它称为循环不变量。它可以在循环之外使用,但对于循环来说它非常重要,因为你经常有很多可能性,或者无限多的可能性。

请注意,我使用“谓词”一词来表示计算机软件的逻辑,而不是证明。这是因为虽然在数学不变量中可以用作证明,但它永远不能证明计算机软件在执行时会产生预期的结果,因为软件是在许多抽象之上执行的,这是永远无法证明的他们将产生预期的结果(例如考虑硬件抽象)。

最后,虽然理论上和严格地预测软件逻辑只对医疗和军事等高度关键的应用程序很重要。在调试时,不变量仍然可以用来帮助典型的程序员。它可以用来知道某个位置的位置 程序失败是因为它未能保持某个不变量——我们中的许多人无论如何都在使用它而没有考虑它。

于 2019-09-07T18:29:49.627 回答
1

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

于 2013-05-23T10:16:17.923 回答
1

Class Invariant是在调用相关函数之前和之后应该始终为真的条件

例如平衡树有一个Invariant叫做isBalanced。当您通过某些方法(例如 addNode、removeNode...)修改树时 -isBalanced在修改树之前和之后应该始终为 true

于 2020-11-11T14:27:42.893 回答
0

Java Concurrency in Practice一书中有一个关于不变量及其重要性的极好示例。

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

在此处输入图像描述

于 2019-07-09T17:55:20.240 回答