什么是先决条件和后置条件?

时间:2016-02-09 22:20:44

标签: programming-languages design-by-contract preconditions post-conditions

我正在学习如何编程,但有一件事我能理解我的想法是先决条件和后置条件

在调用一个被认为是前置条件的函数之前是一个if语句,还是在大多数语言中有一个单独的更有效的方法呢?

我也在努力寻找任何先决条件的例子,如果有人能证明一个简单的编程,我能理解当前的编程知识,那么我会非常感激(任何语言都会没事)

2 个答案:

答案 0 :(得分:2)

这是一个计算机科学问题,而不是编程问题,所以它更适合于https://cs.stackexchange.com/,但无论如何我都会回答它。

考虑这个程序来找到大海捞针的第一个索引。 (大海捞针可能包含许多针;我们想要停在第一个针上。)如果干草堆没有针,则索引等于干草堆的大小(这不是大海捞针的有效索引) )。

i = 0
while i < haystack.count && haystack[i] != needle {
    i = i + 1
}

“后置条件”是关于程序状态的断言,通常表示程序已经计算了一些有用的东西(在后置条件点)。对于示例程序,我们可以编写后置条件,声明它计算了我们想要的结果:

i = 0
while i < haystack.count && haystack[i] != needle {
    i = i + 1
}
assert(i == haystack.count || haystack[i] == needle) // first postcondition
haystack[0 ..< i].forEach { assert($0 != needle) } // second postcondition

(注意:0 ..< i表示所有j都是0 ≤ j < i。)

第一个后置条件断言,i是大海捞针中的项目数,或者i是指针的索引。

第二个后置条件断言,在指南i之前的任何地方,针都不会出现在大海捞针中。因此程序找到了第一根针,如果发现任何针头。

因此,如果这些后置条件成立,程序就会按照我们的要求行事。

“前提条件”是关于程序状态的断言,当与程序的后续动作结合时,可用于证明后置条件。我们可以为示例程序添加前置条件:

i = 0
while i < haystack.count && haystack[i] != needle {
    haystack[0 ... i].forEach { assert($0 != needle) } // precondition
    i = i + 1
}
assert(i == haystack.count || haystack[i] == needle) // first postcondition
haystack[0 ..< i].forEach { assert($0 != needle) } // second postcondition

(注意:0 ... i表示所有j都是0 ≤ j ≤ i。)

前提条件告诉我们所有干草堆元素直到并包括索引i处的元素都不是针。

每次程序到达时,您都可以使用induction来证明前提条件为真。当循环条件为假时循环结束,这意味着第一个后置条件为真。 (第一个后置条件是循环条件的对立。)循环前置条件为真的事实意味着第二个后置条件也是正确的。

答案 1 :(得分:2)

c++'s paper

中有充分说明
  
      
  • 前置条件是一个谓词,应该保持进入一个函数。它在参数和/或函数可能使用的对象状态上表达函数的期望

  •   
  • 后置条件是一个谓词,应该保持退出一个函数。它表示函数应确保返回值条件和/或函数可能使用的对象的状态。

  •   

前提条件后置条件属于基于合同的编程。

在Dlang,基于合同的编程具有良好的设计。 This document提供了一个示例:

long square_root(long x)
in
{
    assert(x >= 0);
}
out (result)
{
    assert(result ^^ 2 <= x && (result + 1) ^^ 2 > x);
}
do
{
    return cast(long)std.math.sqrt(cast(real)x);
}

前置条件位于in块中,后置条件位于out块中。

  • 如果满足前提条件后置条件,那么它会愉快地编译,就像将9传递给函数一样。 live demo
  • 如果不满足前置条件,就像将-1传递给函数一样。 live demo
      

    core.exception.AssertError@prog.d(8):断言失败

  • 如果后置条件不满意,可能是因为我们没有处理do块中的逻辑,例如返回square而不是{{ 1}},然后,后置条件将起作用:live demo
      

    core.exception.AssertError@prog.d(13):断言失败

对于课程,Dlang也有很好的工具,请阅读the document以了解更多信息

BTW,c ++还将合同设计列入c ++ 20的草案:https://www.reddit.com/r/cpp/comments/8prqzm/2018_rapperswil_iso_c_committee_trip_report/

Here是提案,也许有助于理解它们(虽然比D,丑陋得多)