【问题标题】:Converting a function to deal with Double and Float... using FloatingPoint type?转换一个函数来处理 Double 和 Float... 使用 FloatingPoint 类型?
【发布时间】:2019-02-25 03:55:13
【问题描述】:

我在 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。

我曾考虑用FloatingPoint 替换Double,但它根本行不通,并给我带来一堆错误。

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

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

有没有办法做到这一点?

除此之外,我如何将 var 或数组声明为 FloatingPoint 类型,我的意思是,同时接受 FloatDouble

【问题讨论】:

    标签: swift floating-point double


    【解决方案1】:

    按照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
    }
    

    【讨论】:

    • 哇,这对我来说是古老的克林贡语。愿意解释它是如何工作的吗?谢谢。
    • 其中 80% 是普通的旧泛型。如果需要,请阅读 Swift 书中的泛型章节。最后 20%(从链接的答案中获得)是支持使用泛型调用 cos 函数的技巧。
    【解决方案2】:

    添加到@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() 一词对于单个表达式来说太复杂了。为什么0.5factor 是什么?我们为什么要使用cosine?这是非常不明显的。这段代码的陌生人不仅不会理解这一点,而且随着时间的推移,你自己也会忘记这一点,成为代码的“陌生人”。

    【讨论】:

      猜你喜欢
      • 2012-01-08
      • 2018-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-24
      相关资源
      最近更新 更多