R 中的逻辑、流程控制和函数

R 是一种过程式编程语言。因此,它拥有与其他许多语言一样的完整流程控制语法集。实际上,R 语言中的流程控制语法与 Java 和 C 相似。在这篇文章中,你将看到一些在 R 语言中使用流程控制语法的例子。

让我们开始吧。

R 中的逻辑、流程控制和函数
图片由 Cris DiNoto 拍摄。保留部分权利。

概述

这篇文章分为三个部分;它们是

  • 寻找素数
  • 埃拉托斯特尼筛法
  • 最长连续素数之和

寻找素数

让我们从一个简单的问题开始:找出小于某个数 N 的所有素数列表。

第一个素数是 2。任何大于 2 的整数,如果不能被任何小于它的素数整除,那么它就是素数。这是一个简单的定义。我们可以将其转换为 R 程序,如下所示:

如果你能成功运行,你将看到以下输出

上述代码的算法如下:你从 2 扫描到 `pmax`(包括两端),对于每个数字 `i`,你使用另一个 for 循环来检查任何现有素数 `j` 是否能整除当前数字。如果 `i %% j == 0`,你就知道 `i` 不是素数。因此你将 `isPrime` 标记为 `FALSE` 并停止。

在每次迭代结束时,素数会被添加到 `prime` 向量中。当程序结束时,该向量将包含上限以下的所有素数。

从上面可以看出 R 语言的一些基本特性。R 中的条件分支语法如下:

这种语法类似于 JavaScript,尽管用于标记每个语句末尾的分号是可选的。

条件应该是布尔值。因此,我们可以使用上面的逻辑变量 `isPrime`,或者比较语句 `i %% j == 0`。运算符 `%%` 用于取模除法。你可以找到常见的 R 运算符及其优先级表如下:

你可以在 R 中使用帮助语句“`?Syntax`”(“Syntax”大写 S)找到此表。

在 C 和 Java 中,你可能会记得有一个三元运算符“`condition?value_true:value_false`”。这是一个运算符,因为它的使用仅限于根据条件的真值返回一个值(`value_true` 或 `value_false`),而不是执行一大段代码。R 中也有类似的功能,作为一个函数:

但你不应该将其与 if-else 语句混淆。

此外,你可以使用与 C 或 Java 类似的嵌套 if 语法

然而,R 中没有 `switch` 语句。相反,`switch()` 是一个函数,其语法如下所示:

在前面的例子中,你还看到了如何在 R 中创建 for 循环:你需要提供一个向量,循环将逐个扫描向量元素。for 循环不要求迭代整数,上面的代码只是一个例子。

当你处于循环中时,你总是可以使用 `break` 语句提前终止循环,或者使用 `next` 语句提前开始下一次迭代。另一个例子如下。

埃拉托斯特尼筛法

如果你将上限设置为更高的值(例如,一百万),则前面寻找素数的例子会很慢。更快的算法是埃拉托斯特尼筛法,代价是会占用略多一些的内存。其思想是每次找到一个素数,然后将它的所有倍数从素数候选列表中排除。

R 中埃拉托斯特尼筛法的实现如下:

这段代码应该产生与前一个代码相同的输出。

在上面的代码中,你看到了如何使用 `next` 和 `break` 语句来控制 for 循环的流程。你还可以看到如何使用 `rep()` 函数创建具有相同值(`TRUE`)的向量,以及如何使用 `seq()` 函数创建从 `i*i` 到 `pmax` 均匀间隔的向量。

在代码的最后,你使用 `which()` 函数来查找向量值为 `TRUE` 的索引。在 R 中,向量是从 1 开始索引的。因此,`primality` 向量在 for 循环开始前被创建,并将第一个元素设置为 `FALSE`(因为 1 不被认为是素数)。

R 中有许多内置函数。上面的代码向你展示了一些,你可以从“R 参考卡片”中学习一些最常用的函数。

最长连续素数之和

如上编写程序对许多项目都很有用,但是当你遇到一个更大的问题时,你可能需要一种将程序组织成功能块的方法。R 不仅支持内置函数,还允许你创建自己的函数。

让我们考虑一个稍大的程序。这是来自 Project Euler 的问题 50。你想要找出一百万以下,且由最长连续素数之和组成的素数。例如,前 6 个素数之和是 2+3+5+7+11+13=41,而 41 是一个素数。答案是 997651,它是 543 个素数之和。

既然你有一种方法可以生成达到一百万的素数,你可以扫描素数向量并求和,然后验证该和是否也是素数,直到该和小于一百万。同时,你需要跟踪符合条件的最长素数之和。

以下是如何在 R 中解决这个问题:

你可以看到,一个自定义函数被创建来返回所有素数的列表。函数使用 `function()` 语法和 `return()` 定义。当你调用函数,例如 `primes <- getprimes(pmax)` 时,`return()` 返回的任何值都会被赋给该变量。

上述代码的其余部分应该对你来说很熟悉:它们是由 for 循环和 if 语句构建的。你应该还会看到答案是如何在循环中记录和更新的。

你应该注意一个微妙的问题:在 `i` 的 for 循环中,它一直到 `length(primes)-1`,而 `j` 的 for 循环从 `i+1` 开始。这是为了确保我们正确计算和,因为在 R 中,可以使用 5:2 或 5:5 这样的语法创建向量,它们分别是一个降序序列和一个单元素向量。

如果你正确运行代码,你应该会看到以下输出:

这告诉你 997651 是 543 个素数之和。

进一步阅读

您可以从以下来源了解有关上述主题的更多信息:

网站

书籍

总结

在这篇文章中,你通过示例学习了一些 R 编程语法以及如何定义自己的 R 函数。具体来说,你学习了:

  • 如何创建循环和分支
  • 如何使用 next 和 break 控制循环中的流程
  • 如何创建和使用自定义函数

暂无评论。

发表评论

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。