C语言 数学中的函数和编程中的函数有什么区别?

yws3nbqq  于 2022-12-22  发布在  其他
关注(0)|答案(6)|浏览(277)

数学中的函数和编程中的函数有什么区别?

uemypmqf

uemypmqf1#

在函数式编程中,我们有Referential Transparency,这意味着可以用函数的值替换函数,而不需要修改程序。* 这在数学中也是正确的*,但在命令式语言中并不总是正确的*。

  • 数学函数 * 定义如下:一种将元素从一个集合(A)Map到另一个集合(B)的关系,第一个集合中的每个元素只与另一个集合中的一个元素Map。在C语言中(与其它程序设计语言一样)也是如此,你有输入集和输出集(几乎总是一个)。

主要的区别在于,如果你在数学中调用f(x),你总是得到相同的答案,但是如果你在C中调用f'(x),答案可能不一样--相同的参数并不总是返回相同的输出。而且取决于程序中的其他东西(封闭作用域、全局变量、内置函数、状态(如果使用面向对象))。
math函数和C函数的另一个区别是,在Math中,您不能创建从非空集到空集的函数(在C中,这将是:你不需要总是返回一些东西),而且,不是所有的函数都是computable(我不知道在数学中是否有类似的东西),你没有无限集的函数(你有有限的内存,所以可能的输入参数集必须是有限的),但是在数学中,你可以定义一个无限集的函数(比如f:N -〉N)和uncountable集合(如f:R -〉R)(在C中你有浮点数,但它们只表示真实的的简化集,这是有限的)。

总结

在C语言中,您并不总是具有引用透明度。您的函数可能并不总是为相同的输入参数给予相同的输出。您可以拥有为无限输入集定义的数学函数,但在C语言函数中,您的输入是有限的。在C语言函数中,您可以拥有不返回任何值的函数,但在数学中,您不能拥有这种函数(如果你有一个有非空输入集的函数,你必须将每个元素Map到另一个集合中的一个)。

thigvfpy

thigvfpy2#

这取决于领域(我不是指功能的领域,我是指学习的领域),也可能取决于语言。
在数学中,对于给定的输入值,一个函数的输入只能Map到一个输出(请记住,垂直线测试);在编程中,这可能并不完全相同,这取决于你在“输入”和“函数逻辑”之间画的线。
例如,假设我们有一个函数兰德(),它读取大气条件以得到一个真正的随机数,再假设一个调用函数将一个整型参数作为排序的乘数,那么下面这个函数是函数吗?

int giveRandAtmosWithMul(int mult)
{
    return mult * rand();
}

从数学意义上讲,如果您将mult视为问题的唯一输入,那么它可能不是一个函数,但显然兰德()也提供了输入(尽管rand()在机器代码中总是具有相同的入口点)。
正如您所看到的,如果没有一些大家都同意的标准协议,这些差异实际上是无法客观定义的。

mw3dktmi

mw3dktmi3#

我认为最重要的区别是数学(和函数式编程)中的函数不能改变状态,而(命令式)编程函数可以。

omhiaaxx

omhiaaxx4#

其他答案都是正确的--这是两件不同的事情,相反,我将证明它们是相关的,我将用->表示编程函数,用=>表示数学函数。
假设你有一种支持异常的语言。在这种情况下,你可以把一个编程函数A -> B想象成一个数学函数A => B + E,其中“B + E”表示B类型的东西,或者E类型的东西。你的语言有两个从函数返回的关键字,“return”和“throw”。
现在,您可以通过编写g(f(x))来组合两个函数f: A -> Bg: B -> C。这是一个接受A并返回C的函数。您可以在许多语言(如Java或Python)中执行此操作。实际上,如果f(x)抛出异常,g不会被调用,异常会被传播--想想g(1/0),语言会处理这个问题,你不需要检查f的结果是否是一个异常。数学上的描述方式是,虽然f: A => B+Eg: B => C+E,但语言将函数g“提升”为B+E => C+Eg现在是一个可能发生异常的函数,但它只会传播异常。
换句话说,定义g': B+E => C+E

/   g(x)   if x ∈ B
g'(x)= |
        \   x      if x ∈ E

有了两个函数f: A => B+Eg': B+E => C+E,你可以安全地在数学意义上把它们组合起来,这就是g(f(x))在编程中所做的,但是它必须先把g提升到g'
考虑一下不确定性,如果你有一个不确定的函数A -> B,你可以用数学的方法描述它,这是一个函数A => Set(B),其中Set(B)是可能结果的集合,例如,如果f(1)可能给予你1,2或3,那么数学上就是f(1) = {1,2,3},尽管在编程时,当要求输入f(1)时,你只能得到其中一个,现在你可以通过写g(f(x))来组合非确定性函数A->BB->C。结果将为C类型,但它是不确定的。从数学上讲,组合函数A => Set(B)B => Set(C)会得到A => Set(C)。尽管g只接受B的一个值,但必须将其提升为不确定的值g': Set(B) => Set(C)。例如,g'({1,2})是集合g(1)g(2)的并集。因此g(f(x))意味着您运行f,获取所有可能结果的集合,并对每个结果运行g。存在两层不确定性,但它们被“扁平化”为一层。
全局状态也一样,如果你把每个全局变量都作为函数的参数和结果,你可以认为没有全局变量,每个函数都取所有的全局状态,语言在编写时必须移交状态。一个函数A -> B阅读并可能写入状态S是一个函数(A,S) => (B,S),也可以写成A => (S => (B,S)),正式写起来要复杂一些,但是模式是一样的。
输入/输出也可以这样做,我在另一个SO answer中描述过。
允许组合“有效”函数的“魔力”是:

  • 一种使类型有效的方法。例如,将B转换为B+ESet(B)。我将类型X的有效版本表示为F(X)
  • 提升功能的方法:B -> F(C)F(B) -> F(C)中,允许组合函数A -> F(B)B -> F(C)
  • 关键字return必须将普通值A转换为A+E,或者单例值Set(A),所以它的类型必须是X -> F(X)

由这三个单子组成的结构称为单子。单子允许描述那些副作用。单子也可能有一些特定的功能,例如异常单子有throw,非确定性单子有fork,状态单子有get/put,IO单子有read/write等。
这个故事的寓意是:如果你把随机化、异常、非确定性、输入/输出等特殊效果看作函数结果的一部分,那么每个函数都是引用透明的,命令式编程中的函数实际上是数学函数,但具有非常奇怪的结果类型,这些结果类型也描述了特殊效果,这是纯函数式语言如Haskell所采用的方法。

z31licg0

z31licg05#

在数学中,函数不会抛出异常。:)
计算机科学中的函数是一段代码,它接受输入,执行某项操作,并可能返回输出,但它可以在这两者之间执行许多操作,它可以获取网页、发送电子邮件、播放视频,等等。
在数学中,函数是非常具体的东西,不是别的。函数通常被描述为一台接受输入并吐出输出的“机器”。而计算机科学函数确实接受输入并吐出输出,他们不需要像数学那样精确的“相同的输入总是产生相同的输出(例如,bool IsMyApplicationRunningInFullScreen()返回各种值,而根本没有输入)。

e4eetjau

e4eetjau6#

数学函数本质上是声明性的,即它们总是有“是什么”的描述,而计算机科学中的函数是命令性的,即它们有“如何”的描述。
参考资料:计算机程序的结构和解释.

相关问题