代码之家  ›  专栏  ›  技术社区  ›  Duck

转换一个函数来处理Double和Float…使用FloatingPoint类型?

  •  0
  • Duck  · 技术社区  · 7 年前

    我在SO上看到过类似的问题,但它并没有回答我在这里提出的所有问题。

    我有这样一个函数:

      func myFunctionDouble (_ valores:[Double] = []) -> Array<Double> {
    
        let numeroItens = valores.count
        var c = [Double](repeating: 0,
                         count: numeroItens)
    
        let factor : Double = Double.pi / Double(numeroItens)
    
        for i in 0..<numeroItens {
          var sum : Double = 0
          for j in 0..<numeroItens {
            sum = sum + valores[j] * cos ((Double(j) + 0.5) * Double(i) * factor)
          }
          c[i] = sum
        }
        return c;
      }
    

    我想转换这个函数来处理Double和Float。

    我想换一个 Double 具有 FloatingPoint 但它根本不起作用,给我带来一大堆错误。

    没有 FloatingPoint.pi 或数组 c 不能像

    var c = [FloatingPoint](repeating: 0, count: numeroItens)
    

    有办法吗?

    除此之外,我如何声明一个var或数组是 浮点数 打字,我的意思是,两者都要接受 Float 双重的 ?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Alexander    7 年前

    遵循中所述的示例 Rob's 答复 How to use FloatingPoint generic type for Float/Double ,您可以执行以下操作:

    import Darwin // minimal necessary import
    // importing Foundation, AppKit or UIKit also implicitly import Darwin
    
    protocol Cosineable {
        func cosine() -> Self
    }
    
    extension Float: Cosineable {
        func cosine() -> Float { return cos(self) }
    }
    
    extension Double: Cosineable {
        func cosine() -> Double { return cos(self) }
    }
    
    func myFunction<T: FloatingPoint>(_ valores:[T] = []) -> Array<T> where T: ExpressibleByFloatLiteral, T: Cosineable {
    
        let numeroItens = valores.count
        var c = [T](repeating: 0,
                         count: numeroItens)
    
        let factor : T = T.pi / T(numeroItens)
    
        for i in 0..<numeroItens {
            var sum : T = 0
            for j in 0..<numeroItens {
                sum += valores[j] * ((T(j) + 0.5) * T(i) * factor).cosine()
            }
            c[i] = sum
        }
        return c
    }
    
        2
  •  2
  •   Alexander    7 年前

    再加上@rmaddy的解决方案,您可以通过使用高阶函数来消除所有“噪声”,从而大大简化代码,这些噪声是计算所必需的,但实际上并不特定于您的计算。

    func myFunction<T: FloatingPoint>(_ valores:[T] = []) -> Array<T>
        where T: ExpressibleByFloatLiteral, T: Cosineable {
        let factor: T = T.pi / T(valores.count)
    
        return valores.indices.map { i in
            return valores.enumerated()
                .map { (offset, element) in
                    element * ((T(offset) + 0.5) * T(i) * factor).cosine()
                }
                .reduce(0, +)
        }
    }
    

    从这里开始,您可以更好地标记这些术语,并提供更多关于这些术语用途的上下文。

    术语 element * ((T(offset) + 0.5) * T(i) * factor).cosine() faaaarrrr对于单个表达式来说太复杂了吗。为什么? 0.5 factor ? 我们为什么要走这条路 cosine ? 这很不明显。不熟悉此代码的人不仅不会理解这一点,而且随着时间的推移,您自己也会忘记这一点,成为代码的“陌生人”。