Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Optimization 如何优化此计算_Optimization_Formula_Floating Accuracy - Fatal编程技术网

Optimization 如何优化此计算

Optimization 如何优化此计算,optimization,formula,floating-accuracy,Optimization,Formula,Floating Accuracy,我正在编写一个模型检查器,它依赖于一个系数的计算,该系数由以下算法密集使用: !![备选案文][1] 其中,q是双精度,t也是双精度,kint.e代表指数函数。该系数用于q和t不改变的步骤,而k总是从0开始,直到(该步骤的)所有先前系数之和达到1为止 我的第一个实现是文字实现: let rec fact k = match k with 0 | 1 -> 1 | n -> n * (fact (k - 1)) let coeff q t k = exp(-. q

我正在编写一个模型检查器,它依赖于一个系数的计算,该系数由以下算法密集使用:

!![备选案文][1]

其中,
q
是双精度,
t
也是双精度,
k
int.
e
代表指数函数。该系数用于
q
t
不改变的步骤,而
k
总是从0开始,直到(该步骤的)所有先前系数之和达到1为止

我的第一个实现是文字实现:

let rec fact k =
  match k with
    0 | 1 -> 1
    | n -> n * (fact (k - 1))

let coeff q t k = exp(-. q *. t) *. ((q *. t) ** (float k)) /. float (fact k)
当然,这并没有持续太久,因为当
k
超过一个小阈值(15-20)时,计算整个阶乘是不可行的:显然结果开始变得疯狂。因此,我通过增量分区重新安排了整个过程:

let rec div_by_fact v d =
  match d with
    1. | 0. -> v
    | d -> div_by_fact (v /. d) (d -. 1.)

let coeff q t k = div_by_fact (exp(-. q *. t) *. ((q *. t) ** (float k))) (float k)
q
t
足够“正常”时,这个版本运行得很好,但当事情变得奇怪时,例如
q=50.0
t=100.0
我开始从
k=0到100
计算它,我得到的是一系列0,后面是从某个数字到最后的NaN

当然,这是由数字开始太接近0的操作或类似问题造成的

您知道我如何优化公式,以便在广泛的输入范围内提供足够准确的结果吗

所有内容都应该是64位的(因为我使用的是默认情况下使用double的OCaml)。也许有一种方法也可以使用128位双工,但我不知道如何使用

我使用OCAML,但你可以用你想要的任何语言提供想法:C、C++、java等等。我很用它们。

qt^k/k! = e^[log[qt^k/k!]]
log[qt^k/k!] = log[qt^k] - log[k!] // log[k!] ~ klnk - k  by stirling
             ~ k ln(qt) - (k lnk - k)
             ~ k ln(qt/k) - k
对于较小的k值,斯特林近似是不精确的。 然而,由于您似乎在执行有限的已知范围,所以可以计算
log[k!]
并将其放入数组中,以避免任何错误

当然,你可以做更多的修改。

这不是一个答案(我相信),但可能只是一个澄清。如果我误解了什么,我会在你的评论后删除它

据我所知,你在试图计算n,比如下面的和等于1

正如你可能看到的,它渐近地接近1,它永远不会等于1。
如果我误解了你的问题,请纠正我。

log
+sum(k=0,…)x^k/k!==exp(x),所以看起来您正在执行exp(-qt)*exp(qt)=1。还是我遗漏了什么?请注意,如果qt较大,则可以使用exp(qt)=exp(qt/2)^2,也就是说,您可以将qt除以2足够的次数,以使序列变短,然后将该次数平方以获得所需的答案。不确定这是否对你所做的有用。是的,你是对的,我使用了equal,但我的意思是足够接近1.0。我实际上要做的是选择一个错误,例如
e=1e-6
,这样
sum>1-e
。我尝试了你建议的分析方法,但仍然没有获得类似的结果。。我会继续努力!同时,我分解了操作以保持在浮动范围内。