2016-03-03 51 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這對數字更加具體。

您也可以瀏覽該庫的源代碼,只提取您需要爲您的具體情況的代碼。