- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我是函数式语言的初学者,我正试图在 Haskell 中完成所有事情。这是一个快速而简单的函数,可以找到一个数的所有因数:
factors :: (Integral a) => a -> [a]
factors x = filter (\z -> x `mod` z == 0) [2..x `div` 2]
工作正常,但我发现它对于大量数据来说太慢了。所以我让自己变得更好:
factorcalc :: (Integral a) => a -> a -> [a] -> [a]
factorcalc x y z
| y `elem` z = sort z
| x `mod` y == 0 = factorcalc x (y+1) (z ++ [y] ++ [(x `div` y)])
| otherwise = factorcalc x (y+1) z
但这就是我的问题:即使代码有效,并且可以减少我程序的执行时间,但它太可怕了!
它散发着丑陋的命令式思维的味道:它在循环中不断更新计数器和数据结构,直到完成。由于您无法在纯函数式编程中更改状态,因此我通过将数据保存在参数中来作弊,函数只是一遍又一遍地将这些数据传递给自身。
我可能是错的,但一定有更好的方法来做同样的事情......
最佳答案
请注意,原始问题询问的是所有 因素,而不仅仅是主要 因素。主要因素少得多,可能可以更快地找到它们。也许这就是 OQ 想要的。也许不是。但让我们解决最初的问题,把“乐趣”放回“功能”!
一些观察:
这两个函数不会产生相同的输出——如果 x 是一个完全平方,则第二个函数包括两次平方根。
第一个函数 enumerates 检查与 x 的大小成比例的一些潜在因素;第二个函数仅检查与x 的平方根
成正比,然后停止(存在上述错误)。
第一个函数 (factors
) 分配一个列表,其中包含从 2 到 n div 2
的所有整数,其中第二个函数从不分配列表,而是访问更少 参数中一次一个整数。我使用 -O
运行优化器并使用 -ddump-simpl
查看输出,GHC 不够智能,无法优化这些分配。
factorcalc
是尾递归的,这意味着它编译成一个紧密的机器代码循环; filter
不是也不是。
一些实验表明平方根是 killer :
下面是一个生成 x 从 z 到 2 的因数的示例函数:
factors_from x 1 = []
factors_from x z
| x `mod` z == 0 = z : factors_from x (z-1)
| otherwise = factors_from x (z-1)
factors'' x = factors_from x (x `div` 2)
它快一点,因为它不分配,但它仍然不是尾递归的。
这是一个更忠实于原始版本的尾递归版本:
factors_from' x 1 l = l
factors_from' x z l
| x `mod` z == 0 = factors_from' x (z-1) (z:l)
| otherwise = factors_from' x (z-1) l
factors''' x = factors_from x (x `div` 2)
这仍然比 factorcalc
慢,因为它枚举了从 2 到 x div 2
的所有整数,而 factorcalc
停止在平方根处.
有了这些知识,我们现在可以创建一个功能更强大的 factorcalc
版本,它可以复制它的速度和错误:
factors'''' x = sort $ uncurry (++) $ unzip $ takeWhile (uncurry (<=)) $
[ (z, x `div` z) | z <- [2..x], x `mod` z == 0 ]
我没有准确计时,但输入 1 亿,它和 factorcalc
都会立即终止,而其他的都需要几秒钟。
该函数如何工作以及为什么工作留给读者作为练习:-)
附录:好的,为了减轻眼球出血,这里有一个稍微更理智的版本(并且没有错误):
saneFactors x = sort $ concat $ takeWhile small $
[ pair z | z <- [2..], x `mod` z == 0 ]
where pair z = if z * z == x then [z] else [z, x `div` z]
small [z, z'] = z < z'
small [z] = True
关于algorithm - 功能性学习困境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/880329/
我正在使用 OneWayToSource绑定(bind),它似乎总是将我的源属性设置为空。为什么呢?这给我带来了麻烦,因为我需要源属性中目标属性的值而不是空值。 这是我的代码: MyViewModel
我有一个实例变量属性,它被声明和实例化,如下所示: $self->{properties}{$key1} = $value; 我的理解是这将声明属性字段,并将其设置为包含一个键值对的哈希原语。 我正
我正在尝试检查给定的数字是否是质数。首先采用试分割法。但该程序的行为很奇怪。这是我使用的。 int no; no = Integer.parseInt(jTextField1.getText());
我正在使用 NSUserDefaults使一个对象在多个 UIViewController 之间保持同步UITabbarController 中使用的 s .为此,我正在实现以下 - (void)vi
考虑以下 Java 方法: public Boolean compare(String val1, String val2) { return val1.length() > 0 && val
我有一个问题...假设我有一个包含城市名称的表。像这样: id name 1 Los Angeles 2 Madrid 我有一张用户表: uid username locationid
我无法理解这个问题。该代码非常基本,但它的行为却出乎意料。该代码是例程的简化版本,用于从每日数据库中提取每月第 15 天的数据并将其保存到单独的文件中。哪里有问题 ?第一个 cout 打印输入外部 i
我在 中使用大背景标签,我想制作一个宽度为 960px 的容器 div。我希望容器 div 位于从顶部向下 15px 的位置,我想我必须使用 position:absolute。我的困境是;容器内的
我遇到了一个难题。我有一个 hashedX 字段,它是一个散列值/加盐值,按照惯例,加盐值保存在 mysql 数据库的同一行中。 hashedX saltX ------ ---
类 java.io.Reader 和 java.io.InputStreamReader 都有具有完全相同签名的读取方法 public int read(char[] charbuf, int off
我有一个包含多个 C# 项目的 C# 解决方案。我打算在其中添加日志记录。此日志记录应该在所有项目中可用,并且最好使用带有滚动文件日志的 log4Net。 在上述前提下,我可以想到两种方法。 在解决方
我开始学习Python,目前我非常喜欢它。但是,如果你能帮我回答几个问题,这些问题一直困扰着我,我找不到任何明确的答案: 就语言兼容性而言,Python 的 C 实现(来自 python.org 的主
我正在尝试使用 AVAssetWriter 将 CGImages 写入文件以从图像创建视频。 我已经让它在模拟器上以三种不同的方式成功运行,但在运行 iOS 4.3 的 iPhone 4 上,每种方法
我需要对一个想法进行建模,可以将其分解并考虑如下: 图书详细信息 图书价格 这里的问题是您可以为书籍设置许多价格,并且这些价格可能会发生变化。这是一个例子 图书详细信息: --------------
我有一个表,其中的行包含名为 MySubId 的列。此列中的值可以重复。我想找到 MySubId 值和出现次数最多的 MySubId 值的行数。 我有以下查询: SELECT MySubId, COU
我有两个具有多对多关系的类,因此我在它们之间创建了一个联接表(一个非常经典的示例!) 在java+hibernate中我想知道哪种方式更好?使用hibernate多对多注释在这两个类之间有多对多关系吗
我正在尝试创建一个 Android 应用程序来完成以下任务:它通过短信向一组收件人(存储在数组中的数字)发送初始调查问题。然后,对于收到的每个响应,它都会向该参与者发送该系列中的下一个问题。这是我做过
这里有一个关于 IncludeEventHandler 的有趣问题。 我正在开发一个基于 Spring 的应用程序,该应用程序使用具有单独投资组合站点的不同供应商的速度。我让供应商通过向他们提供存储在
我真的无法理解事件和委托(delegate)的概念。我知道委托(delegate)是持有方法引用的对象,可以调用具有相同返回类型和参数的方法,但事件到底是什么? 如果我需要使用事件来制作一个简单的计算
在我正在处理的一个项目中,我有一个扩展 JFrame 的主类(名为 TrackWin)。在此框架中,我使用 JTabbedPane。 用户可以从菜单栏在 Pane 中创建新选项卡。每当发生这种情况时,
我是一名优秀的程序员,十分优秀!