2016-03-03 53 views
0

我发现这个neat trick计算的平均值和标准差在一遍数据。我想要这个工作float32floatAgain,我很努力地用通用数字来解决这个问题。如何统一这两个浮点函数?

module Seq = 
    let inline private avgVarianceReducer toFloat (count, oldM, oldS) x = 
     if count = 1 then 
      2, x, LanguagePrimitives.GenericZero 
     else 
      let meanFree = x - oldM 
      let newM = oldM + meanFree/(toFloat count) 
      count + 1, newM, oldS + meanFree * (x - newM) 

    let inline private avgVarianceWith toFloat source = 
     match source |> Seq.fold (avgVarianceReducer toFloat) (1, LanguagePrimitives.GenericZero, LanguagePrimitives.GenericZero) with 
     | 0, _, _ -> LanguagePrimitives.GenericZero, LanguagePrimitives.GenericZero 
     | 1, mean, _ -> mean, LanguagePrimitives.GenericZero 
     | n, mean, var -> mean, var/(n - 2 |> toFloat) 

    let avgVariance source = source |> avgVarianceWith float 
    let avgVariancef source = source |> avgVarianceWith float32 

这适用于这两种类型,但我有额外的加avgVariancef我不得不选择打电话的时候是正确的。

对我来说,核心问题是转换到avgVarianceReducer一种权利浮动的,我通过传递正确的转换funtion解决。我尝试了op_Explicit,但失败了。

人有一个更优雅的解决方案的想法?

回答

3

你试过FSharpPlus? 它包含一个通用数学模块和您正在寻找的通用explicit函数。

这里是你的代码会是什么样子:

#r @"FsControl.dll" 
#r @"FSharpPlus.dll" 

open FSharpPlus 
open FSharpPlus.Operators.GenericMath 

module Seq = 
    let inline private avgVarianceReducer (count, oldM, oldS) (x:'R) = 
     if count = 1 then 
      2, x, 0G 
     else 
      let meanFree = x - oldM 
      let newM = oldM + meanFree/explicit count 
      count + 1, newM, oldS + meanFree * (x - newM) 

    let inline avgVariance source : 'R * 'R = 
     match source |> Seq.fold avgVarianceReducer (1, 0G, 0G) with 
     | 0, _, _ -> 0G, 0G 
     | 1, mean, _ -> mean, 0G 
     | n, mean, var -> mean, var/(n - 2 |> explicit) 

    // or if you prefer specific functions 
    let avgVarianceF32 source : float32 * float32 = avgVariance source 
    let avgVarianceF source : float * float = avgVariance source 

    // it will work with other types as well 
    let avgVarianceD source : decimal * decimal = avgVariance source 

其实你并不需要的功能explicit,您可以改用功能fromIntegral这对数字更加具体。

您也可以浏览该库的源代码,只提取您需要为您的具体情况的代码。