gpt4 book ai didi

ruby - 什么相当于 Haskell 中 Ruby 的 pnormaldist 统计函数?

转载 作者:数据小太阳 更新时间:2023-10-29 06:57:16 28 4
gpt4 key购买 nike

如下所示:http://www.evanmiller.org/how-not-to-sort-by-average-rating.html

这是在 Statistics2 中实现的 Ruby 代码本身图书馆:

# inverse of normal distribution ([2])
# Pr( (-\infty, x] ) = qn -> x
def pnormaldist(qn)
b = [1.570796288, 0.03706987906, -0.8364353589e-3,
-0.2250947176e-3, 0.6841218299e-5, 0.5824238515e-5,
-0.104527497e-5, 0.8360937017e-7, -0.3231081277e-8,
0.3657763036e-10, 0.6936233982e-12]

if(qn < 0.0 || 1.0 < qn)
$stderr.printf("Error : qn <= 0 or qn >= 1 in pnorm()!\n")
return 0.0;
end
qn == 0.5 and return 0.0

w1 = qn
qn > 0.5 and w1 = 1.0 - w1
w3 = -Math.log(4.0 * w1 * (1.0 - w1))
w1 = b[0]
1.upto 10 do |i|
w1 += b[i] * w3**i;
end
qn > 0.5 and return Math.sqrt(w1 * w3)
-Math.sqrt(w1 * w3)
end

最佳答案

这很容易翻译:

module PNormalDist where

pnormaldist :: (Ord a, Floating a) => a -> Either String a
pnormaldist qn
| qn < 0 || 1 < qn = Left "Error: qn must be in [0,1]"
| qn == 0.5 = Right 0.0
| otherwise = Right $
let w3 = negate . log $ 4 * qn * (1 - qn)
b = [ 1.570796288, 0.03706987906, -0.8364353589e-3,
-0.2250947176e-3, 0.6841218299e-5, 0.5824238515e-5,
-0.104527497e-5, 0.8360937017e-7, -0.3231081277e-8,
0.3657763036e-10, 0.6936233982e-12]
w1 = sum . zipWith (*) b $ iterate (*w3) 1
in (signum $ qn - 0.5) * sqrt (w1 * w3)

首先,让我们看看 ruby​​ - 它返回一个值,但有时它会打印一条错误消息(当给出不正确的参数时)。这不是很 haskellish,所以让我们的返回值为 Either String a - 我们将返回 Left String如果给定不正确的参数,则显示错误消息,并显示 Right a否则。

现在我们检查顶部的两种情况:

  • qn < 0 || 1 < qn = Left "Error: qn must be in [0,1]" - 这是错误条件,当qn超出范围。
  • qn == 0.5 = Right 0.0 - 这是 ruby 支票 qn == 0.5 and return * 0.0

接下来,我们定义w1在 ruby 代码中。但是我们在几行之后重新定义了它,这不是很 ruby 。我们存储在 w1 中的值第一次在 w3 的定义中立即使用,那么我们为什么不跳过将它存储在 w1 中呢? ?我们甚至不需要做 qn > 0.5 and w1 = 1.0 - w1步骤,因为我们使用产品 w1 * (1.0 - w1)在 w3 的定义中。

所以我们跳过所有这些,直接进入定义 w3 = negate . log $ 4 * qn * (1 - qn) .

接下来是 b 的定义,这是对 ruby​​ 代码的直接提升(ruby 的数组文字语法是 haskell 的列表语法)。

这是最棘手的一点 - 定义 w3 的最终值. ruby代码在

中做了什么
w1 = b[0]
1.upto 10 do |i|
w1 += b[i] * w3**i;
end

就是所谓的折叠 - 将一组值(存储在 ruby​​ 数组中)减少为单个值。我们可以使用 Array#reduce 在功能上(但仍然在 ruby​​ 中)重申这一点:

w1 = b.zip(0..10).reduce(0) do |accum, (bval,i)|
accum + bval * w3^i
end

注意我是如何推送 b[0] 的进入循环,使用标识 b[0] == b[0] * w3^0 .

现在我们可以将其直接移植到 haskell 中,但是它有点难看

w1 = foldl 0 (\accum (bval,i) -> accum + bval * w3**i) $ zip b [0..10]

相反,我把它分成几个步骤 - 首先,我们真的不需要 i ,我们只需要 w3 的权力(从 w3^0 == 1 开始),所以让我们用iterate (*w3) 1来计算那些.

然后,我们最终只需要它们的产品,而不是将它们与 b 的元素成对压缩,因此我们可以将它们压缩到每对产品使用 zipWith (*) b .

现在我们的折叠功能真的很简单 - 我们只需要总结产品,我们可以使用 sum 来完成.

最后,我们决定返回正负 sqrt (w1 * w3) , 根据是否qn大于或小于 0.5(我们已经知道它不相等)。因此,与其像在 ruby​​ 代码中那样在两个不同的位置计算平方根,我算了一次,乘以+1-1根据qn - 0.5的标志( signum just returns the sign of a value )。

关于ruby - 什么相当于 Haskell 中 Ruby 的 pnormaldist 统计函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6116770/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com