Language agnostic 什么是不变量?

Language agnostic 什么是不变量?,language-agnostic,invariants,Language Agnostic,Invariants,这个词似乎在许多上下文中使用。我能理解的最好的情况是,它们意味着一个无法改变的变量。这不就是常量/韵母(该死的Java!)的用途吗?这是一个条件,您知道在逻辑中的某个特定位置始终为真,并且可以在调试时进行检查以找出哪里出了问题。我通常更多地从算法或结构的角度来看待它们 例如,您可以有一个可以断言的循环不变量——在每次迭代的开始或结束时总是true。也就是说,如果您的循环应该处理从一个堆栈到另一个堆栈的对象集合,您可以说| stack1 |+| stack2 |=c,位于循环的顶部或底部 如果不变

这个词似乎在许多上下文中使用。我能理解的最好的情况是,它们意味着一个无法改变的变量。这不就是常量/韵母(该死的Java!)的用途吗?

这是一个条件,您知道在逻辑中的某个特定位置始终为真,并且可以在调试时进行检查以找出哪里出了问题。

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

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

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

维基百科的魔力:

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

不变量比变量更“概念化”。一般来说,程序状态的一个属性总是正确的。确保不变量保持不变的函数或方法被称为保持不变量

// sum is the sum of the first count grades
例如,二叉搜索树可能具有不变量,即对于每个节点,节点左子节点的密钥小于节点自己的密钥。为此树正确编写的插入函数将保持不变

// sum is the sum of the first count grades

正如您所知,这不是您可以存储在变量中的类型:它更多地是关于程序的语句。通过找出程序应该维护哪种类型的不变量,然后检查代码以确保它确实维护了这些不变量,可以避免代码中的逻辑错误。

根据不变量的性质,不变量在编写干净的代码时非常有用,因为从概念上知道代码中应该存在哪些不变量,所以可以轻松决定如何组织代码以达到这些目标。正如前面提到的,它们在调试中也很有用,因为检查是否维护了不变量通常是一种很好的方法,可以查看您试图执行的任何操作是否真的在做您希望它做的事情。

在一个代码块内不会改变的某件事。

ADT不变量指定了关系 在数据字段中(实例变量) 这在前后都必须是正确的 任何实例方法的执行。

如此行所述:

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

为了更好地理解这个希望,C++中的这个例子有帮助。 考虑一个场景,在这个场景中,您必须获取一些值,并在名为
count
的变量中获取它们的总计数,然后将它们添加到名为
sum
的变量中

不变量(同样,它更像一个概念): 上面的代码应该是这样的

int count=0;
double sum=0,x=0;
while (cin >> x) {
++count;
sum+=x;
}
while(cin>>x){
 ++count; 
 }
while(cin>>x){
 ++count; 
 sum+=x;
 }
上面的代码是做什么的

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

2) 一次成功读取后,递增
count
sum=sum+x

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

循环不变量: 不变量必须始终为真。因此,最初,您只需使用以下内容开始编写代码

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

如何保持不变量为真? 简单!增量计数

所以<代码>++计数会很好的!。现在我们的代码变成这样

int count=0;
double sum=0,x=0;
while (cin >> x) {
++count;
sum+=x;
}
while(cin>>x){
 ++count; 
 }
while(cin>>x){
 ++count; 
 sum+=x;
 }
但是 即使现在我们的不变量(一个必须为真的概念)也是错误的,因为现在我们没有满足我们的不变量的第二部分

// sum is the sum of the first count grades
那么现在该怎么办呢

x
添加到
sum
中,并将其存储在
sum
sum+=x
)中,下次
cin>>x
将把一个新值读入x

现在我们的代码变成这样

int count=0;
double sum=0,x=0;
while (cin >> x) {
++count;
sum+=x;
}
while(cin>>x){
 ++count; 
 }
while(cin>>x){
 ++count; 
 sum+=x;
 }
让我们检查一下 代码是否匹配我们的不变量 代码:

啊!。现在循环不变量始终为真,代码工作正常


上述示例取自Andrew koening和Barbara-E的《加速C++
一书,并对其进行了修改。它通常是一个在某些数学运算下不会改变的量。
示例是一个标量,在旋转下不会改变。例如,在磁共振成像中,通过旋转不变量来描述组织特性是很有用的,因为这样一来,它的估计在理想情况下并不取决于扫描仪中身体的方向。

这本书中有一个不变量的极好例子,以及它的重要性

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


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

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

下面是一个证明,如果你能找到一个处于初始状态的不变量,并且无论对该状态应用任何[法律]变换,该不变量都会持续存在,那么你可以证明