使用FloatingPoint类型将函数转换为处理Double和Float ...吗?

时间:2019-02-25 03:55:14

标签: swift floating-point double

我在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或数组为FloatingPoint类型,我的意思是要同时接受FloatDouble

2 个答案:

答案 0 :(得分:2)

按照Rob'sHow 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
}

答案 1 :(得分: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?这不是很明显。对此代码的陌生人不仅不理解这一点,而且随着时间的流逝,您自己会忘记这一点,并成为代码的“陌生人”。