简体   繁体   English

如何在Haskell中解决此数学函数?

[英]How to solve this math Function in Haskell?

How can I solve this math Funcion with Haskell? 如何使用Haskell解决此数学函数? Can anyone help me? 谁能帮我?

Rekursive math Function 递归数学函数

myFunc n m = myFuncRec n m if m <= n then 1
                       else myFuncRec n(m - 1):[]

Do I need two recursion? 我需要两次递归吗? because for this problem in java needs two or three loops. 因为在Java中此问题需要两个或三个循环。

I would normally give a hint instead of a full solution, but since this question is mostly about syntax, and the translation is very close, almost literal, I'll just give it to you in full. 我通常会给出提示,而不是提供完整的解决方案,但是由于这个问题主要是关于语法的,而且翻译非常接近,几乎是字面意义,因此我将其完整地介绍给您。

数学的东西

p n m 
    | m <= n    = 1
    | otherwise = sum [ p n (m - i) | i <- [1..n] ]

The bars distinguishing the different cases by conditions are called guards , and the bracket structure in the last line is known as a list comprehension . 通过条件区分不同情况的横杠被称为警卫 ,最后一行的括号结构被称为列表理解

luqui's answer gives the natural, straightforward translation of the math definition into Haskell code. luqui的答案将数学定义自然而直接地转换为Haskell代码。 As a specification, it is perfect: beautiful and obviously correct. 作为一个规范,它是完美的:美丽且显然正确。 As a teaching tool, it is perfect: easy to read, easy to understand, and no advanced features used. 作为一种教学工具,它是完美的:易于阅读,易于理解,并且不使用任何高级功能。 But as an algorithm it is a little unfortunate: the existence of many recursive calls that each do recomputation makes it very slow for large inputs. 但是,作为一种算法,它有点不幸:每个递归调用都存在许多递归调用,这对于大输入量来说非常慢。 So in this answer I will give a taste of what a solution not intended for simplicity might look like. 因此,在这个答案中,我将介绍一下并非旨在简化的解决方案。

One observation of interest is that P(2,-) is the Fibonacci sequence, which has a well-known, beautiful, and efficient definition as an infinite list in Haskell: 有趣的观察结果是P(2,-)是斐波那契数列,它在Haskell中具有无穷列表的众所周知,优美而有效的定义:

fibs = 1:1:zipWith (+) fibs (tail fibs)

This recursively-defined list uses itself as a memoization table. 该递归定义的列表将其自身用作备注表。 One might ask whether there is a clean generalization of this trick to P with other first arguments than 2; 也许有人会问,这个技巧对P是否具有除2以外的其他第一个自变量的干净概括。 the answer is yes. 答案是肯定的。 The basic idea is this: since transpose is the natural extension of zip to arbitrary arity, and sum is the natural extension of (+) to arbitrary arity, we can write: 基本思想是:由于transposezip对任意arity的自然扩展,而sum(+)对任意arity的自然扩展,因此我们可以这样写:

import Data.List

transposeWith :: ([a] -> b) -> [[a]] -> [b]
transposeWith f xss = map f (transpose xss)

genFib :: Int -> [Integer]
genFib n = result where
    result = replicate n 1 ++ transposeWith sum [drop i result | i <- [0..n-1]]

This gives us an efficient way to compute P(n,-) for any n , using a list for memoization. 这为我们提供了一种有效的方法,即使用列表进行记忆来计算任意n P(n,-) If we wish to memoize even the n dimension, we can write: 如果我们想记住n维,我们可以这样写:

p :: [[Integer]]
p = map genFib [1..]

How much faster is it? 它快多少? On my machine, computing P(100, 130) takes luqui's solution more than ten minutes (and appears to roughly double in time each time you add one to m ), while my solution responds in under a second for even such a large input as P(100, 10000) . 在我的机器上,计算P(100, 130) 100,130 P(100, 130)会花费luqui的解决方案超过十分钟(并且每次将m加1时,时间大约会增加一倍),而我的解决方案即使在输入如此大的输入时,响应时间也不到一秒钟P(100, 10000)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM