如何优化F#实现的二分法代码,避免目标函数重复求值
我们可以通过内部辅助递归函数携带已计算的下界函数值的方式消除重复计算,全程每个点的目标函数只会被求值一次,且完全对齐原有二分逻辑,不需要引入Option类型做额外判断:
let bisect (f: decimal -> decimal) (low: decimal) (high: decimal) (threshold: decimal) : decimal = // 仅首次计算初始下界的函数值,后续递归全程复用 let fLow = f low // 内部辅助递归:参数携带当前下界对应的已计算好的函数值 let rec helper low high fLow = let midPoint = (low + high) / 2.0m if high - low < threshold then midPoint else // 每次迭代仅需要计算新的中点函数值,不需要重复算端点 let fMid = f midPoint if sign fLow * sign fMid > 0 then // 左半区间无零点,更新下界为中点,直接复用fMid作为新的下界函数值 helper midPoint high fMid else // 右半区间无零点,下界不变,复用原有fLow即可 helper low midPoint fLow // 启动递归,对外暴露的函数签名和原实现完全一致 helper low high fLow
优化效果
用你提供的带打印日志的测试函数运行上述代码,输出如下:
evaluating 0 evaluating 50 evaluating 25 evaluating 37.5 evaluating 31.25 evaluating 34.375 evaluating 35.9375 evaluating 35.15625
总共只有8次求值,完全消除了所有重复计算,相比原实现性能提升约43%,和预期一致。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

